home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / byepc300.zip / BYE300.ASM < prev    next >
Assembly Source File  |  1987-11-05  |  100KB  |  3,123 lines

  1.            PAGE 62,132
  2.            TITLE BYE-PC Version 3.00 - Resident Modem Driver
  3. ;-----------------------------------------------------------------------
  4. ;          * * *  BYE-PC Resident Modem Driver  * * *
  5. ;
  6. ;           (c) Copyright 1986, 1987 MCODE Software
  7. ;                  by
  8. ;            R. E. Starr, Jr.
  9. ;            3444 Dresden Dr.
  10. ;              Montgomery Al. 36111
  11. ;             (205)244-7230
  12. ;-----------------------------------------------------------------------
  13. ;
  14. ;        Many thanks to the following people for
  15. ;           making this project possible:
  16. ;
  17. ;            - William C. Bryan -
  18. ;
  19. ;     Special thanks to Bill for the hardware timing functions
  20. ;     and guidance during initial project development.
  21. ;
  22. ;              - Greg Gross -
  23. ;
  24. ;     Special thanks to Greg for the endless hours of online de-
  25. ;     bugging. Almost all of the online debugging was performed by
  26. ;     Greg.
  27. ;
  28. ;-----------------------------------------------------------------------
  29. ;-------------------- General Equates Section --------------------------
  30. ;-----------------------------------------------------------------------
  31. ;
  32. PGM_VER        equ  3           ;BYE-PC version number
  33. PGM_REV        equ  0           ;BYE-PC revision level
  34. ;
  35. ;   -- general purpose equates --
  36. ;
  37. YES           equ  1           ;boolean defines
  38. NO           equ  0
  39. ON           equ  1
  40. OFF           equ  0
  41.  
  42. EOF           equ  -1           ;end of file
  43. NULL           equ  0           ;zero value
  44. CR           equ  0Dh        ;carriage return
  45. LF           equ  0Ah        ;line feed
  46. ESK           equ  1Bh        ;escape (ESC is an instruction)
  47. BKSPC           equ  08h
  48. BELL           equ  7           ;ring bell through tty print
  49. CTRL_C           equ  03h        ;remote break control key
  50. CTRL_S           equ  13h        ;remote pause key
  51. ;
  52. ;   -- keyboard scan codes --
  53. ;
  54. ALT_Q           equ  16           ;top row keys
  55. ALT_W           equ  17
  56. ALT_E           equ  18
  57. ALT_R           equ  19
  58. ALT_T           equ  20
  59. ALT_Y           equ  21
  60. ALT_U           equ  22
  61. ALT_I           equ  23
  62. ALT_O           equ  24
  63. ALT_P           equ  25
  64.  
  65. ALT_A           equ  30           ;middle row keys
  66. ALT_S           equ  31
  67. ALT_D           equ  32
  68. ALT_F           equ  33
  69. ALT_G           equ  34
  70. ALT_H           equ  35
  71. ALT_J           equ  36
  72. ALT_K           equ  37
  73. ALT_L           equ  38
  74.  
  75. ALT_Z           equ  44           ;bottom row keys
  76. ALT_X           equ  45
  77. ALT_C           equ  46
  78. ALT_V           equ  47
  79. ALT_B           equ  48
  80. ALT_N           equ  49
  81. ALT_M           equ  50
  82. ;
  83. ;   -- baud rate initialization for 8255 --
  84. ;
  85. BPS300           equ  0180h       ;port initialize (300 bps)
  86. BPS600           equ  00C0h       ;port initialize (600 bps)
  87. BPS1200        equ  0060h       ;port initialize (1200 bps)
  88. BPS2400        equ  0030h       ;port initialize (2400 bps)
  89. BPS3600        equ  0020h       ;port initialize (3600 bps)
  90. BPS4800        equ  0018h       ;port initialize (4800 bps)
  91. BPS7200        equ  0010h       ;port initialize (7200 bps)
  92. BPS9600        equ  000Ch       ;port initialize (9600 bps)
  93.  
  94. INT_RX           equ  0           ;Set the Rx-Interrupt mode
  95. INT_TX           equ  1           ;Set the Tx-Interrupt mode
  96. INT_STAT       equ  2           ;Set the Status Interrupt mode
  97. ;
  98. ;   -- system hardware addresses --
  99. ;
  100. EOI           equ  20h        ;end of interrupt command
  101. IO_8259        equ  20h        ;8259 PIC interrupt controller port
  102. PORT_TM        equ  40h        ;8253 timer i/o port
  103. PORT_PA        equ  60h        ;8255 PPI keyboard input port
  104. PORT_PB        equ  PORT_PA+1       ;8255 PPI in/out keyboard & cassette
  105. PORT_PC        equ  PORT_PA+2       ;8255 PPI input from planer switches
  106.                    ; (COM1=03F8h, COM2=02F8h)
  107. WBOOT_OFF      equ  0E05Bh       ;IBM-PC Warm boot offset
  108. WBOOT_SEG      equ  0F000h       ;IBM-PC Warm boot segment
  109. ;
  110. ;***********************************************************************
  111. ;******************** PROGRAM CONFIGURATION SECTION ********************
  112. ;***********************************************************************
  113. ;
  114. ; COMM Port selection equates, all three of these must be changed in
  115. ; order to change the COMM port used for the modem.
  116. ;
  117. ;
  118. RS232_INT      equ  0Ch        ;rs232 vector (0Ch=COM1, 0Bh=COM2)
  119. IRQ_BASE       equ  10h        ;(IRQ4=10h:COM1, IRQ3=08h:COM2)
  120. PORT_BASE      equ  03F8h       ;8255 rs232 i/o base port address
  121.                    ;03F8h=COM1, 02F8h=COM2
  122. ;
  123. ; Receive buffer queue size. This is the actual size of the ring
  124. ; buffer in bytes used by the rs-232 interrupt routines.
  125. ;
  126. RX_BUFF        equ  256        ;rx-data interrupt queue size
  127. ;
  128. ; YES if you are using a Hayes compatable command set modem. If NO, then
  129. ; use the CD line to wait for carrier and sync to baud by checking for
  130. ; a carriage return to appear at the port (remote must send CR's). This
  131. ; is for dumb modems, such as the Universal Data Systems 212b with auto-
  132. ; answer capability only.
  133. ;
  134. SMART_MDM      equ  YES        ;yes, if you are using a smart modem
  135. ;
  136. ; Select ONLY ONE of these baud rates for your modems highest baud rate!
  137. ;
  138. BPS_300        equ  NO           ;max baud rate 300bps?
  139. BPS_1200       equ  YES        ;max baud rate 1200bps?
  140. BPS_2400       equ  NO           ;max baud rate 2400bps?
  141. TELEBIT        equ  NO           ;Telebit Trailblazer 9600 only!
  142. ;
  143. ; Set to YES for the Telebit Trailblazer, If the rx-queue becomes full,
  144. ; the RTS line is asserted false to tell the modem to halt sending data.
  145. ;
  146. USE_RTS        equ  NO           ;yes, ask nulls question
  147. ;
  148. ; Yes for nulls, you may need to ask for nulls if you have 2400ps mdm.
  149. ;
  150. USE_NULLS      equ  YES        ;yes, ask nulls question
  151. ;
  152. ; Yes to run a COM/EXE file upon receiveing a valid carrier.
  153. ;
  154. LOGON_EXE      equ  YES        ;yes, execute XBBS during logon
  155. ;
  156. ; If YES, re-boot after running 'COM/EXE' file locally.
  157. ;
  158. REBOOT           equ  NO           ;no,  exit to dos after 'run local'
  159. ;
  160. ; Initial time allowed on system. This can be read and set via INT66
  161. ; function numbers 17 & 18. Normally set/reset by XBBS after log on.
  162. ;
  163. TIME           equ  60           ;initial time on system limit
  164. ;
  165. ; Ctrl-S timeout, after timeout is reached Ctrl-S pause if reset.
  166. ;
  167. TIMEOUT        equ  30           ;30 seconds during Ctrl-S pause
  168. ;
  169. ; This sets the limit for remote type ahead during 'stdin' operations.
  170. ; If the limit is exceeded (noise), the rx queue is flushed and reset.
  171. ;
  172. KEYLIM           equ  32           ;up to 32 chars at once
  173. ;
  174. ; Allows optional call to old interrupt 1C service routine. This will
  175. ; be an 'iret' instruction if no other resident programs loaded.
  176. ;
  177. CHAIN_INT1C    equ  YES        ;call old interrupt 1C
  178. ;
  179. ; Local keyboard control key mapping. These keys become active
  180. ; when the caller makes connection.
  181. ;
  182. K_END           equ  79           ;[End] key to exit msg from sys/op
  183. K_REMOTE       equ  ALT_B       ;toggle remote on off key
  184. K_LOGOFF       equ  ALT_O       ;send log off message
  185. K_HANGUP       equ  ALT_H       ;hangup on caller and re-boot
  186. K_CHAT           equ  ALT_Q       ;message from sysop key
  187. K_BELL           equ  ALT_G       ;toggle bell on/off
  188. K_CLS           equ  ALT_Z       ;clear the screen locally
  189. K_TIME           equ  ALT_U       ;unlimited time on key
  190. K_SYSOP        equ  ALT_S       ;sys/op status level
  191. K_CALLER       equ  ALT_C       ;display caller on line
  192. ;
  193. ;***********************************************************************
  194. ;****************** END PROGRAM CONFIGURATION SECTION ******************
  195. ;***********************************************************************
  196. ;
  197. rom_bios_data  SEGMENT at 40h             ;ROM Bios data area SEGMENT
  198.            ORG 72h
  199. reset_flag     dw ?                 ;ALT-CTRL-DEL pressed flag
  200. rom_bios_data  ENDS
  201. ;
  202. ;   -- set up the segment and begin exection --
  203. ;
  204. code           SEGMENT para public 'code'
  205.            ASSUME cs:code, ds:code, es:code, ss:code
  206.            ORG 100h
  207.  
  208. start:           jmp  initialize             ;goto loader routine.
  209. ;
  210.            PAGE
  211. ;-----------------------------------------------------------------------
  212. ;----------------------- PROGRAM DATA AREA -----------------------------
  213. ;-----------------------------------------------------------------------
  214. ;
  215. ; NOTE: Do not remove copyright as "byexface.c" uses this to
  216. ;    determine if BYE-PC is resident in memory.
  217. ;
  218. ;-----------------------------------------------------------------------
  219. ;
  220. copyrite       db   "BYE-PC  (c) Copyright 1986, 1987 MCODE Software"
  221.            db   01Ah        ;Do not alter this string!!!
  222. bye_sign       dw   1234h        ;BYE-PC signiture when installed
  223. ;
  224. ;   -- Terminal Configuration Data --
  225. ;    (Televideo 910/912/920/925/950)
  226. ;
  227. cls_cnt        db   2            ;#bytes to send cls
  228. cls_bytes      db   ESK,':',0,0,0,0    ;clear screen data
  229.  
  230. loc_cnt        db   2            ;#bytes to locate cursor
  231. loc_bytes      db   ESK,'=',0,0,0,0    ;locate cursor prefix data
  232.  
  233. namebuf        db   64 dup(0)        ;caller name buffer.
  234. ;
  235. ;    -- System Messages and Strings --
  236. ;
  237. lost_msg       db   0Dh,0Ah,0Dh,0Ah
  238.            db   "[Carrier Lost]",0Dh,0Ah,"$"
  239. timeup_msg     db   0Dh,0Ah,0Dh,0Ah
  240.            db   "[Time Limit Expired]",0Dh,0Ah,0Dh,0Ah,"$"
  241. off_msg        db   ": Off]$"
  242. on_msg           db   ": On]$"
  243. remote_msg     db   "[Remote$"
  244. bell_msg       db   "[Bell$"
  245. utime_msg      db   "[Unlimited Time]$"
  246. logoff_msg     db   "[System Going down in 2 Mins!]$"
  247. chat_msg       db   "Message from Sys/Op: $"
  248. sysop_msg      db   "[Sys/Op Privledges]$"
  249. caller_msg     db   "[Caller on line: $"
  250. ;
  251. ;-----------------------------------------------------------------------
  252. ;------------------- Program Flags & Varibles Area----------------------
  253. ;-----------------------------------------------------------------------
  254. ;
  255. baud           db   0          ;call baud rate (0=300,1=1200,3=2400)
  256. nulls           db   0          ;# of nulls to send
  257. time_on        db   TIME      ;minutes allowed online
  258. cd_lost        db   NO          ;carrier lost detect flag
  259. bell_flg       db   ON          ;local bell state
  260. brk_flg        db   ON          ;Ctrl-Break enable from remote on
  261. trap_flg       db   OFF       ;^S & ^C trap enable flag
  262. tout_flg       db   ON          ;timeout during pause flag on
  263. cstat           dw   0FFFFh    ;caller status byte (0-255)
  264. ;
  265. ; --Interrupt Data Storage Areas --
  266. ;
  267. old_int09      dd   ?          ;storage for old keybd service int
  268. old_int10      dd   ?          ;storage for old video int
  269. old_int13      dd   ?          ;storage for old disk interrupt
  270. old_int16      dd   ?          ;storage for old keybd access int
  271. old_int1C      dd   ?          ;storage for old timer interrupt
  272. ;
  273. ; -- Program status and system flags --
  274. ;
  275. timer_tick     dw   0          ;timer tick counter
  276. timer_min      db   0          ;timer tick minutes counter
  277. int10_merge    db   ON          ;merge characters 'to' screen & mdm
  278. int16_merge    db   ON          ;merge characters 'from' screen & mdm
  279. cd_check       db   ON          ;checking carrier detect status
  280. scan_key       db   EOF       ;scan code key storage.
  281. local_flg      db   0          ;program already active flag.
  282. disk_flg       db   0          ;disk int 13h busy flag
  283. pause_req      db   0          ;Ctrl-S pressed flag
  284. pause_flg      db   0          ;Ctrl-S pressed flag
  285. recur_flg      db   0          ;int10 re-entrance flag
  286.          IF USE_RTS
  287. rts_flg        db   ON          ;rts on/off state flag
  288.          ENDIF
  289. ;
  290. ; -- Receive interrupt data storage --
  291. ;
  292. rx_head        dw   0            ;queue starting ptr
  293. rx_tail        dw   0            ;queue ending ptr
  294. rx_cnt           dw   0            ;# of chars in rx-queue
  295. rx_buf           db   RX_BUFF+1 dup(0)    ;rx-queue buffer
  296. ;
  297. ;
  298.            PAGE
  299.            SUBTTL     *** Keyboard Service Interrupt ***
  300. ;---INT-09--------------------------------------------------------------
  301. ;Keyboard service interrupt to load all characters from the keyboard.
  302. ;This routine traps all keyboard interrupts from the BIOS and checks
  303. ;for the 'hot keys' to enable local control options.
  304. ;-----------------------------------------------------------------------
  305. ;
  306. int09_main     PROC far
  307.  
  308.            sti                 ;re-enable interrupts
  309.            push ds                 ;save registers
  310.            push ax
  311.  
  312.            push cs                 ;DS=CS
  313.            pop  ds
  314.  
  315.            in   al,PORT_PA             ;get scan code.
  316.            mov  scan_key,al          ;save key pressed.
  317.            call lkey_ndx             ;key a local ctrl function?
  318.            cmp  al,EOF             ;no, exit
  319.            je   kb0
  320.            mov  ah,2             ;check shift key status
  321.            int  16h
  322.            test al,8             ;is the Alt key pressed?
  323.            jne  kb2              ;no, then exit
  324.  
  325. kb0:           pop  ax                 ;restore registers
  326.            pop  ds
  327.            jmp  cs:[old_int09]         ;jump to Bios routine
  328.  
  329. ;
  330. ; Reset the keyboard controler and issue an EOI to 8259 controller.
  331. ;
  332. kb2:           in   al,PORT_PB             ;get current control value
  333.            mov  ah,al             ;save it in AH
  334.            or   al,80h             ;set the high bit
  335.            out  PORT_PB,al             ;send it to the control port
  336.            mov  al,ah             ;recover original value
  337.            out  PORT_PB,al             ;send it out
  338.            cli                 ;suspend interrupts
  339.            mov  al,EOI             ;load EOI value
  340.            out  IO_8259,al             ;send it to the 8259
  341.            sti                 ;restore interrupts
  342.  
  343.            cmp  local_flg,NULL         ;local routine already active?
  344.            jne  kb1              ; yes, then exit
  345.            cmp  disk_flg,NULL         ;any disk i/o pending?
  346.            jne  kb1              ; yes, then exit
  347.            call local_ctrl             ;call local key routine
  348.  
  349. kb1:           pop  ax
  350.            pop  ds                 ;end interrupt routine
  351.            iret
  352.  
  353. int09_main     ENDP
  354. ;
  355. ;
  356. ;-----------------------------------------------------------------------
  357. ; LOCAL CONTROL -- This sets up for a call to the local control key
  358. ; functions. After one of the correct hot keys are pressed, control is
  359. ; transferred here to perform the actual function call.
  360. ;-----------------------------------------------------------------------
  361. ;
  362. local_ctrl     PROC near
  363.  
  364.            mov   local_flg,YES         ;set program active flag
  365.            push  ax              ;save all registers
  366.            push  bx
  367.            push  cx
  368.            push  dx
  369.            push  si
  370.            push  di
  371.  
  372.            mov  al,scan_key          ;get scan code stored
  373.            call lkey_ndx             ;key a local ctrl function?
  374.            cmp  al,EOF             ;no, exit
  375.            je   alt_key_end
  376.            xor  bx,bx             ;clear the word
  377.            mov  bl,al             ;load the function number
  378.            shl  bx,1             ;table offset x 2
  379.            call cs:alt_jtbl[bx]         ;call subroutine function#
  380. alt_key_end:
  381.            mov   local_flg,NULL         ;reset status flag
  382.            pop   di
  383.            pop   si
  384.            pop   dx
  385.            pop   cx
  386.            pop   bx
  387.            pop   ax
  388.            ret
  389. ;
  390. ; --- Call table of hot key functions to call ---
  391. ;
  392. alt_jtbl       dw OFFSET loc_remote         ;0 = toggle remote
  393.            dw OFFSET loc_logoff         ;1 = tell user to logoff
  394.            dw OFFSET boot_sys         ;2 = hangup on caller
  395.            dw OFFSET loc_chat         ;3 = enter chat
  396.            dw OFFSET loc_bell         ;4 = toggle bell on/off
  397.            dw OFFSET loc_scrn         ;5 = clear screen
  398.            dw OFFSET loc_utime         ;6 = unlimited time
  399.            dw OFFSET loc_sysop         ;7 = sys/op status
  400.            dw OFFSET loc_caller         ;8 = caller on line
  401.  
  402. local_ctrl     ENDP
  403. ;
  404. ;
  405. ;-----------------------------------------------------------------------
  406. ; LOCAL KEY INDEX -- This function returns the index of the local keybd
  407. ; Alt control keys. If an EOF is returned, the key does not exsists.
  408. ;
  409. ;    Entry     AL = Scan Code of Alt key to check
  410. ;
  411. ;    Return:   AL = EOF if not a local control key option
  412. ;
  413. ;-----------------------------------------------------------------------
  414. ;
  415. lkey_ndx       PROC near
  416.  
  417.            push bx
  418.            xor  bl,bl
  419.  
  420.            cmp  al,K_REMOTE          ;toggle remote on off key
  421.            je   lkey_exit             ;BL = 0
  422.            inc  bl
  423.            cmp  al,K_LOGOFF          ;send log off message
  424.            je   lkey_exit             ;BL = 1
  425.            inc  bl
  426.            cmp  al,K_HANGUP          ;hangup on caller and re-boot
  427.            je   lkey_exit             ;BL = 2
  428.            inc  bl
  429.            cmp  al,K_CHAT             ;message from sysop
  430.            je   lkey_exit             ;BL = 3
  431.            inc  bl
  432.            cmp  al,K_BELL             ;toggle bell on/off
  433.            je   lkey_exit             ;BL = 4
  434.            inc  bl
  435.            cmp  al,K_CLS             ;clear the screen locally
  436.            je   lkey_exit             ;BL = 5
  437.            inc  bl
  438.            cmp  al,K_TIME             ;unlimited time on key
  439.            je   lkey_exit             ;BL = 6
  440.            inc  bl
  441.            cmp  al,K_SYSOP             ;sys/op status
  442.            je   lkey_exit             ;BL = 7
  443.            inc  bl
  444.            cmp  al,K_CALLER          ;display caller on line
  445.            je   lkey_exit             ;BL = 8
  446.            mov  bl,EOF             ;else, invalid key
  447.  
  448. lkey_exit:     mov  al,bl
  449.            pop  bx
  450.            ret
  451.  
  452. lkey_ndx       ENDP
  453. ;
  454. ;
  455.            PAGE
  456.            SUBTTL     *** Video BIOS Interrupt ***
  457. ;---INT-10--------------------------------------------------------------
  458. ; All video writes to the BIOS are translated here and passed to the
  459. ; modem and the screen. This routine directs all the character video
  460. ; writes to the modem and then to the screen. Presently this function
  461. ; traps TTY and write character/attribute calls.
  462. ;-----------------------------------------------------------------------
  463. ;
  464. int10_main     PROC far
  465.  
  466.            sti                 ;re-enable interrupts
  467.            push ds                 ;save DS on the stack
  468.            push cs                 ;DS=CS
  469.            pop  ds
  470.            cmp  int10_merge,NULL         ;exit if ignoring mdm
  471.            je   int10_end
  472.            cmp  recur_flg,0          ;exit if recursive call
  473.            je   int10_entry          ; from old int10 routine
  474. int10_end:     pop  ds
  475.            jmp  cs:[old_int10]         ;go back to old routine
  476. ;
  477. ; Redirect BIOS video writes to go to the modem first.
  478. ;
  479. int10_entry:   push ax                 ;save function register
  480.            cmp  ah,14             ;write tty?
  481.            je   vid_tty             ; yes, send it out
  482.            cmp  ah,10             ;write char at pstn?
  483.            je   vid_con             ; yes, send it out
  484.            cmp  ah,9             ;write char/attr at pstn?
  485.            je   vid_con             ; yes, send it out
  486.            cmp  ah,7             ;scroll down?
  487.            je   vid_cls             ; yes, process it
  488.            cmp  ah,6             ;scroll up?
  489.            je   vid_cls             ; yes, process it
  490.            cmp  ah,2             ;position cursor?
  491.            jne  int10_exit             ; no, exit
  492.  
  493. vid_loc:       push cx                 ;send locate csr prefix
  494.            push si
  495.            mov  cl,loc_cnt
  496.            mov  si,OFFSET loc_bytes
  497.            call tx_puts
  498.            pop  si
  499.            pop  cx
  500.            mov  al,dh             ;send the cursor row#.
  501.            add  al,020h             ;make it ascii
  502.            call tx_putc
  503.            mov  al,dl             ;send the cursor col#.
  504.            add  al,020h             ;make it ascii
  505.            call tx_putc
  506.            jmp  SHORT int10_exit         ;exit to old int10
  507.  
  508. vid_cls:       cmp  al,0             ;is it a clear window?
  509.            jne  int10_exit             ;no, skip sending cls
  510.            cmp  cx,0             ;upper left corner 0,0
  511.            jne  int10_exit
  512.            cmp  dl,79             ;column 79 or greater?
  513.            jl   int10_exit
  514.            cmp  dh,24             ;row 24 or greater?
  515.            jl   int10_exit
  516.            push cx                 ;send clear screen data
  517.            push si
  518.            mov  cl,cls_cnt
  519.            mov  si,OFFSET cls_bytes
  520.            call tx_puts
  521.            pop  si
  522.            pop  cx
  523.            jmp  SHORT int10_exit         ;exit to old int10
  524.  
  525. vid_tty:       call tx_putc             ;char to tx in AL now
  526.            cmp  al,BELL             ;was it a bell?
  527.            jne  int10_exit             ; no, then send it out
  528.            cmp  bell_flg,NULL         ;ok to ring locally?
  529.            jne  int10_exit             ; yes, the ring it.
  530.            pop  ax                 ;get char off stack
  531.            jmp  SHORT int10_exit1         ;exit without bell
  532.  
  533. vid_con:       call tx_char             ;print char with nulls
  534. ;
  535. ;  Restore registers, call the old int10 to service the video display,
  536. ; and then reset the recursion flag before exiting.
  537. ;
  538. int10_exit:    pop  ax                 ;restore function register
  539.            mov  recur_flg,1
  540.            pushf                 ;save the flags
  541.            call old_int10             ;call old bios routine
  542.            mov  recur_flg,0          ;clear recursion flag
  543. int10_exit1:   pop  ds                 ;one last pop for the DS
  544.            iret
  545.  
  546. int10_main     ENDP
  547. ;
  548. ;
  549.            PAGE
  550.            SUBTTL     *** Disk BIOS Interrupt ***
  551. ;---INT-13--------------------------------------------------------------
  552. ; Disk i/o interrupt. This routine sets a flag any time disk i/o is
  553. ; pending. This is used to prevent any local console hot keys from
  554. ; doing anything if any disk i/o is being performed.
  555. ;------------------------------------------------------------------------------
  556. ;
  557. int13_main     PROC far
  558.  
  559.            mov  cs:disk_flg,1         ;set disk 'busy' flag
  560.            pushf                 ;save the flags
  561.            call cs:[old_int13]         ;call old disk int
  562.            mov  cs:disk_flg,0         ;reset disk 'busy' flag
  563.            ret  2                 ;exit with new flags
  564.  
  565. int13_main     ENDP
  566. ;
  567. ;
  568.            PAGE
  569.            SUBTTL     *** Keyboard BIOS Interrupt ***
  570. ;---INT-16--------------------------------------------------------------
  571. ; All keyboard requests to the BIOS are intercepted here. Keyboard BIOS
  572. ; functions #0-(keyboard get character) and #1-(keyboard data availble)
  573. ; are interrcepted here. If the modem rx-queue has data, it is merged
  574. ; before the local keyboard data received. Otherwise, the original BIOS
  575. ; routines are called to service the local keyboard. Note that we could
  576. ; simply stuff the characters in the queue within the rx-data interrupt,
  577. ; but this would prevent us from having more than 15 character type
  578. ; ahead. This method allows the int16 to keep getting chars up to the
  579. ; the maximum rx-queue size.
  580. ;-----------------------------------------------------------------------
  581. ;
  582. int16_main     PROC far
  583.  
  584.            sti                 ;re-enable interrupts
  585.            push ds
  586.            push ax
  587.  
  588.            push cs                 ;DS=CS
  589.            pop  ds
  590.  
  591.            cmp  cd_check,NULL         ;checking cd status?
  592.            je   int16_main1          ;no, skip time check
  593.            call chk_timeon             ;time online is up?
  594. int16_main1:   cmp  int16_merge,NULL         ;ignoring modem input?
  595.            je   skip_int16             ; yes, then jump
  596. ;
  597. ; -- Check for input overflow. If buffer is full ring bell & flush --
  598. ;
  599.            push ax                 ;save ax
  600. flush_all:     call rx_size             ;check remote input limit
  601.            cmp  ax,KEYLIM
  602.            jl   int16_main2          ;if limit reached, reset it
  603.            call rx_flush             ;reset the rx buffer
  604.            cmp  bell_flg,NULL         ;ok to ring bell?
  605.            je   flush_all             ; no, skip it.
  606.            push bx
  607.            mov  bl,2             ; yes, beep on overflow
  608.            call beep
  609.            pop  bx
  610.            jmp  SHORT flush_all         ;flush it out again
  611.  
  612. int16_main2:   pop  ax                 ;restore ax
  613.            or   ah,ah             ;0 = get-a-key
  614.            jz   getkey
  615.            dec  ah                 ;1 = get-keybd-status
  616.            jz   kbhit
  617.  
  618. skip_int16:    pop  ax                 ;recover function#
  619.            pop  ds                 ;recover DS
  620.            jmp  cs:[old_int16]         ;skip shift status, jmp to bios
  621. ;
  622. ; --- check for char waiting at modem, else goto BIOS keybd routine ---
  623. ;
  624. kbhit:           call rx_ready             ;character in the queue?
  625.            jz   skip_int16             ; no, exit through BIOS
  626.            pop  ax                 ;recover function call#
  627.            pop  ds                 ;recover DS
  628.            or   al,1             ;char ready at keybd bit.
  629.            ret  2                 ;return from interrupt with
  630.                          ; flags popped off stack.
  631. ;
  632. ;   --- get a character from modem or keyboard ---
  633. ;
  634. getkey:        call rx_ready             ;character in queue?
  635.            jz   skip_int16             ;jump if no character rdy
  636.            pop  ax                 ;discard int function#
  637. gotkey:        call rx_getc             ;get character from mdm
  638.            and  al,7Fh             ;strip off parity bit 7
  639.            xor  ah,ah             ;clear scan code return
  640.            pop  ds                 ;recover DS
  641.            iret
  642.  
  643. int16_main     ENDP
  644. ;
  645. ;
  646. ;-----------------------------------------------------------------------
  647. ; CHECK TIME ONLINE -- Check to see if timeon has expired, if not exit
  648. ; else tell the caller time is up, hangup,  and re-boot. This function
  649. ; is called before each keyboard get data/status interrupt is processed.
  650. ;-----------------------------------------------------------------------
  651. ;
  652. chk_timeon     PROC near
  653.  
  654.            push ax
  655.            mov  ah,time_on             ;get time limit
  656.            or   ah,0
  657.            jz   check_end             ; no, exit
  658.            cmp  timer_min,ah         ;compare to time passed
  659.            jg   time_up             ;time on < time expired?
  660. check_end:     pop  ax
  661.            ret
  662.  
  663. time_up:       pop  ax
  664.            mov  si,OFFSET timeup_msg     ;tell caller time is up
  665.            call con_puts
  666.            mov  ax,2             ;wait 2 seconds
  667.            call delay             ;fall through and wboot
  668.            jmp  NEAR PTR boot_sys         ;reboot system
  669.  
  670. chk_timeon     ENDP
  671. ;
  672.            PAGE
  673.            SUBTTL     *** Timer Tick Service Interrupt ***
  674. ;---INT-1C--------------------------------------------------------------
  675. ; This routine is called approximatly 18.2 times/second to service the
  676. ; system timer that counts minutes passed since logon. Also, if the
  677. ; keyboard 'request_flg' is set, the alt_key routine is called to serv-
  678. ; ice local keyboard control functions.
  679. ;-----------------------------------------------------------------------
  680. ;
  681. int1C_main     PROC far
  682.  
  683.            sti
  684.            push ds                 ;save DS
  685.  
  686.            push cs                 ;DS=CS
  687.            pop  ds
  688.          IF CHAIN_INT1C
  689.            pushf                 ;save the flags
  690.            call old_int1C             ;call old timer rtn
  691.          ENDIF
  692. ;
  693. ; Check to see if the RTS is off, and if we can turn it on yet.
  694. ; The RTS line is used to control data flows from high speed modems.
  695. ;
  696.          IF USE_RTS
  697.            push ax
  698.            cmp  rts_flg,NULL         ;exit if RTS is on
  699.            jne  skip_rts
  700.            call rx_size             ;get queue size
  701.            cmp  ax,(RX_BUFF/4)         ;3/4 empty yet?
  702.            jg   skip_rts             ;no, leave it off
  703.            mov  rts_flg,ON
  704.            mov  ax,ON             ;turn RTS back on now
  705.            call port_rts
  706. skip_rts:      pop  ax
  707.          ENDIF
  708. ;
  709. ; Increment the time on system clock ticker used to check time-on limit.
  710. ;
  711.            inc  timer_tick
  712.            cmp  timer_tick,1092         ;ticked 1092 times yet?
  713.            jl   int1C_end             ;jmp if not > 1080
  714.            inc  timer_min             ;else, inc minutes...
  715.            mov  timer_tick,0         ;reset the ticker
  716.  
  717. int1C_end:     pop  ds
  718.            iret
  719.  
  720. int1C_main     ENDP
  721. ;
  722.            PAGE
  723.            SUBTTL     *** Applications Program Interface (API) ***
  724. ;-----------------------------------------------------------------------
  725. ;INT66 APPLICATIONS PROGRAM INTERFACE (API) -- This interrupt provides
  726. ; modem i/o for applications which need direct control of the modem.
  727. ;
  728. ;   Altered registers  :  AX, BX, CX, DX
  729. ;              ES (only when funct 21 called)
  730. ;
  731. ;   Preserved registers:  CS, DS, SS, DI, SI, SP, BP
  732. ;
  733. ;-----------------------------------------------------------------------
  734. ; Functions Provided:
  735. ;
  736. ;   AH=0       Get character from modem in AL.
  737. ;            AL=character returned
  738. ;            AH=0 null (no keybd scan codes)
  739. ;            AX = EOF if no data.
  740. ;
  741. ;   AH=1       Put character in AL to modem.
  742. ;            AL=character to send.
  743. ;
  744. ;   AH=2       Hang up the modem (DTR off):
  745. ;            AL=0 turn off dtr
  746. ;            AL=1 turn on dtr
  747. ;
  748. ;   AH=3       Get carrier detect status in AX:
  749. ;            AX=0 no carrier detect found
  750. ;            AX=1 carrier detect found
  751. ;
  752. ;   AH=4       Set carrier detect check status:
  753. ;            AX=0 ignore carrier detect status
  754. ;            AX=1 check carrier detect status
  755. ;
  756. ;   AH=5       Flush the rx queue of all data.
  757. ;
  758. ;   AH=6       Get # of chars in rx queue:
  759. ;            AX=0 rx queue size
  760. ;
  761. ;   AH=7       Get Baud rate of this call in AX:
  762. ;           (0=300bps, 1=1200bps, 3=2400bps)
  763. ;
  764. ;   AH=8       Set Control Break/Pause (CTRL-C/CTRL-S) flag state:
  765. ;            AL=0 CTRL_NOBRK  - disable remote ^C & ^S breaks
  766. ;            AL=1 CTRL_BRK    - enable remote breaks
  767. ;            AL=2 CTRL_NOTOUT - disable ^S pause timeout
  768. ;            AL=3 CTRL_TOUT   - enable ^S timeout
  769. ;            AL=4 CTRL_NOTRAP - dont trap ^C & ^S characters
  770. ;            AL=5 CTRL_TRAP   - allow ^C & ^S to be trapped out
  771. ;
  772. ;   AH=9       Set <stdout> merged with modem:
  773. ;            AL=0 disable output modem
  774. ;            AL=1 enable output to modem
  775. ;
  776. ;   AH=10      Set <stdin> merged with modem:
  777. ;            AL=0 disable input from modem  (rx-queue active)
  778. ;            AL=1 enable input from modem   (rx-queue active)
  779. ;
  780. ;   AH=11      Get BYE-PC version/revison level in AX:
  781. ;            AL=Current Revision level
  782. ;            AH=Current Version level
  783. ;
  784. ;   AH=12      Get number of nulls requested in AX:
  785. ;            AX=Number of nulls requested
  786. ;
  787. ;   AH=13      Set number of nulls to AX:
  788. ;            AL=Number of nulls to send
  789. ;
  790. ;   AH=14      Warm Boot the system through bios Ctrl-Alt-Del.
  791. ;
  792. ;   AH=15      Get the user caller status
  793. ;            AX=Status level (0-FFFFh).
  794. ;
  795. ;   AH=16      Set the user caller status
  796. ;            CX=Status level (0-FFFFh).
  797. ;
  798. ;   AH=17      Set the time limit caller is allowed on line.
  799. ;            AL=number of minutes (0-255, 0=Unlimited).
  800. ;
  801. ;   AH=18      Get the time caller has been on line
  802. ;            AX=number of minutes online (0-255).
  803. ;
  804. ;   AH=19      Set the receive data interrupt mode
  805. ;            AL=Mode (0=Off, 1=On)
  806. ;
  807. ;   AH=20      Get the time limit caller is allowed on line.
  808. ;            AX=number of minutes allowed online (0-255).
  809. ;
  810. ;   AH=21      Get far pointer to caller name buffer.
  811. ;            ES:BX -> far ptr to name buffer
  812. ;
  813. ;   AH=22      Get far pointer to terminal configuration buffer
  814. ;            ES:BX -> far ptr to terminal config buffer
  815. ;
  816. ;-----------------------------------------------------------------------
  817. ;
  818. int66_main     PROC far
  819.  
  820.            sti            ;re-enable interrupts
  821.            push si
  822.            push ds            ;save DS
  823.            push cs
  824.            pop  ds            ;DS=CS for data items
  825.  
  826.            cmp  ah,22        ;check function range
  827.            jg   int66_end
  828.            xor  bh,bh        ;clear the msb of word
  829.            mov  bl,ah        ;load function# in lsb
  830.            shl  bx,1        ;table OFFSET x 2
  831.            call cs:int66_jtbl[bx]    ;call subroutine function#
  832.  
  833. int66_end:     pop  ds            ;restore DS
  834.            pop  si
  835.            iret
  836. ;
  837. ; --- Call table for function # to call ---
  838. ;
  839. int66_jtbl     dw OFFSET rx_getc         ; 0 = mdm get character
  840.            dw OFFSET iputc             ; 1 = mdm put character
  841.            dw OFFSET dtr_state         ; 2 = dtr on/off
  842.            dw OFFSET cd_status         ; 3 = CD status
  843.            dw OFFSET cd_flag         ; 4 = ignore CD state
  844.            dw OFFSET rx_flush         ; 5 = flush Rx queue
  845.            dw OFFSET rx_size         ; 6 = get Rx-size
  846.            dw OFFSET get_bps         ; 7 = get baud rate
  847.            dw OFFSET set_break         ; 8 = set break
  848.            dw OFFSET halt_send         ; 9 = halt loc sending
  849.            dw OFFSET halt_get         ; 10 = halt loc receiving
  850.            dw OFFSET get_vers         ; 11 = get rev level
  851.            dw OFFSET get_nulls         ; 12 = get # of nulls
  852.            dw OFFSET set_nulls         ; 13 = set # of nulls
  853.            dw OFFSET boot_sys         ; 14 = re-boot system
  854.            dw OFFSET get_stat         ; 15 = set status
  855.            dw OFFSET set_stat         ; 16 = get status
  856.            dw OFFSET set_timer         ; 17 = set max time online
  857.            dw OFFSET get_timeon         ; 18 = get time online
  858.            dw OFFSET set_rxint         ; 19 = set rx interrupt
  859.            dw OFFSET get_timer         ; 20 = get max time online
  860.            dw OFFSET get_nameptr         ; 21 = ptr to name buffer
  861.            dw OFFSET get_termptr         ; 22 = ptr to term buffer
  862.  
  863. int66_main     ENDP
  864. ;
  865.            PAGE
  866. ;-----------------------------------------------------------------------
  867. ; INT66 subroutine functions. These are called via software interrupts.
  868. ;-----------------------------------------------------------------------
  869. ;
  870. ; Put character to modem in AL.
  871. ;
  872. iputc           PROC near
  873.  
  874.            call tx_putc             ;char in AL
  875.            xor  ax,ax             ;signal ok
  876. iputc1:        ret
  877.  
  878. iputc           ENDP
  879. ;
  880. ; Return the current status of the carrier detect line.
  881. ;
  882. cd_status      PROC near
  883.  
  884.            call port_cd             ;check CD line
  885.            mov  ax,YES
  886.            jc   cd_stat1             ;jump if CD found
  887.            mov  ax,NULL             ;flag no carrier
  888. cd_stat1:      ret
  889.  
  890. cd_status      ENDP
  891. ;
  892. ; Set/Reset the flag that ignores carrier detect status.
  893. ;
  894. cd_flag        PROC near
  895.  
  896.            or   al,al             ;carrier chk on or off?
  897.            jz   cd_flag1
  898.            mov  cd_check,ON          ;carrier checking on
  899.            cmp  cd_lost,NULL         ;has carrier been lost?
  900.            je   cd_flag2             ; jump if not lost
  901.            jmp  NEAR PTR boot_sys         ; else, re-boot system.
  902. cd_flag1:      mov  cd_check,NULL         ;carrier checking off
  903. cd_flag2:      ret
  904.  
  905. cd_flag        ENDP
  906. ;
  907. ; Toggle the dtr/cts line to the modem to force a hangup.
  908. ;
  909. dtr_state      PROC near
  910.  
  911.            or   al,al
  912.            jz   dtr_state1
  913.            mov  ax,ON
  914.            jmp  SHORT dtr_state2
  915. dtr_state1:    mov  ax,NULL             ;turn OFF the dtr/rts
  916. dtr_state2:    call port_dtr
  917.            ret
  918.  
  919. dtr_state      ENDP
  920. ;
  921. ; Get the baud rate of this call in AX.
  922. ;
  923. get_bps        PROC near
  924.  
  925.            xor  ah,ah             ;clear the msb
  926.            mov  al,baud             ;return baud rate
  927.            ret
  928.  
  929. get_bps        ENDP
  930. ;
  931. ; Set the ctrl-break flag on/off.
  932. ;
  933. set_break      PROC near
  934.  
  935.            or   al,al
  936.            jz   set_brk_off          ;AH=0 - Break/Pause Off
  937.            dec  al
  938.            jz   set_brk_on             ;AH=1 - Break/Pause On
  939.            dec  al
  940.            jz   set_tim_off          ;AH=2 - Pause Timeout Off
  941.            dec  al
  942.            jz   set_tim_on             ;AH=3 - Pause Timeout On
  943.            dec  al
  944.            jz   filter_off             ;AH=4 - Filter/Trap off
  945.            dec  al
  946.            jz   filter_on             ;AH=5 - Filter/Trap On
  947.            jmp  SHORT set_brk_end
  948.  
  949. set_brk_off:   mov  brk_flg,OFF          ;^C break off
  950.            jmp  SHORT set_brk_end
  951. set_brk_on:    mov  brk_flg,ON             ;^C break on
  952.            jmp  SHORT set_brk_end
  953. set_tim_off:   mov  tout_flg,OFF         ;^S time-out off
  954.            jmp  SHORT set_brk_end
  955. set_tim_on:    mov  tout_flg,ON          ;^S time-out on
  956.            jmp  SHORT set_brk_end
  957. filter_off:    mov  trap_flg,OFF         ;^C & ^S trap off
  958.            mov  pause_req,OFF         ;clear ^S pause flag
  959.            jmp  SHORT set_brk_end
  960. filter_on:     mov  trap_flg,ON          ;^C & ^S trap mdm on
  961.  
  962. set_brk_end:   ret
  963.  
  964. set_break      ENDP
  965. ;
  966. ; Set/Reset the flag that ignores chars sent to modem.
  967. ;
  968. halt_send      PROC near
  969.  
  970.            or   al,al
  971.            jz   halt_send1
  972.            mov  int10_merge,ON         ;chars 'to' mdm on
  973.            jmp  SHORT halts_exit
  974. halt_send1:    mov  int10_merge,NULL         ;chars 'to' mdm off
  975. halts_exit:    ret
  976.  
  977. halt_send      ENDP
  978. ;
  979. ; Set/Reset the flag that ignores chars received from modem.
  980. ;
  981. halt_get       PROC near
  982.  
  983.            or   al,al
  984.            jz   halt_get1
  985.            mov  int16_merge,ON         ;chars 'from' mdm on
  986.            jmp  SHORT haltg_exit
  987. halt_get1:     mov  int16_merge,NULL         ;chars 'from' mdm off
  988. haltg_exit:    ret
  989.  
  990. halt_get       ENDP
  991. ;
  992. ; Return the version/revision level in AX.
  993. ;
  994. get_vers       PROC near
  995.  
  996.            mov  al,PGM_REV             ;get rev level
  997.            mov  ah,PGM_VER             ;get vers number
  998.            ret
  999.  
  1000. get_vers       ENDP
  1001. ;
  1002. ; Get the number of nulls currently used.
  1003. ;
  1004. get_nulls      PROC near
  1005.  
  1006.            xor  ah,ah             ;clear msb
  1007.            mov  al,nulls             ;return nulls
  1008.            ret
  1009.  
  1010. get_nulls      ENDP
  1011. ;
  1012. ; Set the number of nulls currently used.
  1013. ;
  1014. set_nulls      PROC near
  1015.  
  1016.            cmp  al,9
  1017.            jle  set_nulls1
  1018.            mov  al,0
  1019. set_nulls1:    mov  nulls,al
  1020.            ret
  1021.  
  1022. set_nulls      ENDP
  1023. ;
  1024. ; Re-Boot the system function.
  1025. ;
  1026. boot_sys       PROC near
  1027.  
  1028.            mov  ax,OFF
  1029.            call port_dtr             ;hang up modem
  1030.            ASSUME ds:rom_bios_data
  1031.            mov  ax,rom_bios_data         ;set DS to rom bios data
  1032.            mov  ds,ax             ; area.
  1033.            mov  reset_flag, 1234h         ;set the alt-ctrl-del flag.
  1034.            db   0EAH             ;jmp to ROM warm boot at:
  1035.            dw   WBOOT_OFF             ; 0E05B OFFSET
  1036.            dw   WBOOT_SEG             ; 0F000 segment
  1037.            ASSUME ds:code
  1038.  
  1039. boot_sys       ENDP
  1040. ;
  1041. ; Get the caller status level.
  1042. ;
  1043. get_stat       PROC near
  1044.  
  1045.            mov  ax,cstat             ;get status level
  1046.            ret
  1047.  
  1048. get_stat       ENDP
  1049. ;
  1050. ; Set the caller status level.
  1051. ;
  1052. set_stat       PROC near
  1053.  
  1054.            mov  cstat,cx             ;set status level
  1055.            ret
  1056.  
  1057. set_stat       ENDP
  1058. ;
  1059. ; Set the callers time limit online allowed.
  1060. ;
  1061. set_timer      PROC near
  1062.  
  1063.            mov  time_on,al             ;save time on allowed
  1064.            mov  timer_tick,0         ;reset timer counter
  1065.            mov  timer_min,0
  1066.            ret
  1067.  
  1068. set_timer      ENDP
  1069. ;
  1070. ; Get the callers time online.
  1071. ;
  1072. get_timeon     PROC near
  1073.  
  1074.            xor  ah,ah
  1075.            mov  al,timer_min         ;return it in AL
  1076.            ret
  1077.  
  1078. get_timeon     ENDP
  1079. ;
  1080. ; Set the receive interrupt mode
  1081. ;
  1082. set_rxint      PROC near
  1083.  
  1084.            and  al,ON             ;toggle for int state
  1085.            mov  ah,INT_RX             ;set rx-interrupt mode
  1086.            call port_imode             ;change interrupt mode
  1087.            call rx_flush             ;clear rx queue
  1088.            ret
  1089.  
  1090. set_rxint      ENDP
  1091. ;
  1092. ; Get the callers time limit online allowed.
  1093. ;
  1094. get_timer      PROC near
  1095.  
  1096.            xor  ah,ah
  1097.            mov  al,time_on             ;save time on allowed
  1098.            ret
  1099.  
  1100. get_timer      ENDP
  1101. ;
  1102. ; Get far ptr to caller name buffer within BYE-PC.
  1103. ;
  1104. get_nameptr    PROC near
  1105.  
  1106.            mov  ax,cs             ;ES=CS
  1107.            mov  es,ax
  1108.            lea bx,namebuf             ;ES:BX points to name buff
  1109.            ret
  1110.  
  1111. get_nameptr    ENDP
  1112. ;
  1113. ; Get far ptr to terminal type buffer within BYE-PC.
  1114. ;
  1115. get_termptr    PROC near
  1116.  
  1117.            mov  ax,cs             ;ES=CS
  1118.            mov  es,ax
  1119.            lea  bx,cls_cnt             ;ES:BX points to term'buff
  1120.            ret
  1121.  
  1122. get_termptr    ENDP
  1123. ;
  1124. ;-----------------------------------------------------------------------
  1125. ; Local keyboard control key subroutines called from INT09 interrupts.
  1126. ;-----------------------------------------------------------------------
  1127. ;
  1128. ; Toggle the remote on/off from 'stdin' and 'stdout'
  1129. ;
  1130. loc_remote     PROC near
  1131.  
  1132.            mov  bl,int10_merge         ;save int10 trap state
  1133.            push bx                 ;save bx reg
  1134.            mov  int10_merge,NULL         ;dont send chars to mdm
  1135.            mov  si,OFFSET remote_msg     ;show header
  1136.            call con_puts
  1137.            pop  bx                 ;restore bx
  1138.            mov  al,bl
  1139.            xor  al,ON             ;now toggle int10 state
  1140.            or   al,al             ;is it off?
  1141.            mov  si,OFFSET off_msg
  1142.            jz   loc_remote1          ;show 'on'/'off' msg
  1143.            mov  si,OFFSET on_msg
  1144. loc_remote1:   call con_puts
  1145.            call rx_flush             ;reset rx-queue
  1146.            mov  int10_merge,al         ;set chars 'to' mdm
  1147.            mov  int16_merge,al         ;set chars 'from' mdm
  1148. ;-->           mov  ah,INT_RX             ;set rx-interrupt mode
  1149. ;-->           call port_imode             ;change interrupt mode
  1150.            ret
  1151.  
  1152. loc_remote     ENDP
  1153. ;
  1154. ; Teller caller to logoff.
  1155. ;
  1156. loc_logoff     PROC near
  1157.  
  1158.            mov  si,OFFSET logoff_msg
  1159.            call con_puts
  1160.            ret
  1161.  
  1162. loc_logoff     ENDP
  1163. ;
  1164. ; Give caller unlimted time.
  1165. ;
  1166. loc_utime      PROC near
  1167.  
  1168.            mov  si,OFFSET utime_msg
  1169.            call con_puts
  1170.            mov  time_on,0             ;disable online timer
  1171.            ret
  1172.  
  1173. loc_utime      ENDP
  1174. ;
  1175. ; Perform local sys/op message
  1176. ;
  1177. loc_chat       PROC near
  1178.  
  1179.            mov  si,OFFSET chat_msg         ;tell'em were breaking in
  1180.            call con_puts
  1181.            mov  al,OFF             ;cut off rx-interrupts
  1182.            mov  ah,INT_RX             ;set rx-interrupt
  1183.            call port_imode             ;change interrupt mode
  1184.            call rx_flush
  1185. loc_chat1:     mov  ah,1             ;see if local keyboard
  1186.            pushf                 ; has char ready.
  1187.            call old_int16
  1188.            jnz  loc_chat1             ;jmp if no character ready
  1189.            mov  ah,0             ;check key press state.
  1190.            pushf
  1191.            call old_int16             ;read the key pressed.
  1192.            cmp  al,0             ;was it a scan code key?
  1193.            jne  loc_chat4             ; no, display the key
  1194.            cmp  ah,K_END             ;[End] key exits chat
  1195.            je   loc_chat_end
  1196.            jp   SHORT loc_chat1         ;continue, wrong scan key
  1197. loc_chat4:     cmp  al,ESK             ;<ESK> key exits chat
  1198.            je   loc_chat_end
  1199.            call con_putc             ;display key received
  1200.            cmp  al,CR
  1201.            jne  loc_chat1             ;if carriage return,
  1202.            mov  al,LF             ; send a line feed also.
  1203.            call con_putc
  1204.            jp   SHORT loc_chat1
  1205. loc_chat_end:  mov  al,ON             ;toggle for int state
  1206.            mov  ah,INT_RX             ;set rx-interrupt mode
  1207.            call port_imode             ;change interrupt mode
  1208.            call rx_flush
  1209.            mov  al,CR             ;send a new line on exit.
  1210.            call con_putc
  1211.            mov  al,LF
  1212.            call con_putc
  1213.            ret
  1214.  
  1215. loc_chat       ENDP
  1216. ;
  1217. ; Toggle the system bell enable flag
  1218. ;
  1219. loc_bell       PROC near
  1220.  
  1221.            mov  bl,int10_merge
  1222.            push bx
  1223.            mov  int10_merge,NULL
  1224.            mov  si,OFFSET bell_msg
  1225.            call con_puts
  1226.            mov  al,bell_flg          ;get current bell state
  1227.            xor  al,YES             ;now toggle it.
  1228.            cmp  al,NULL             ;is it on?
  1229.            mov  si,OFFSET on_msg
  1230.            jne  loc_bell1
  1231.            mov  si,OFFSET off_msg
  1232. loc_bell1:     call con_puts
  1233.            mov  bell_flg,al          ;set new bell state
  1234.            pop  bx
  1235.            mov  int10_merge,bl
  1236.            ret
  1237.  
  1238. loc_bell       ENDP
  1239. ;
  1240. ; Perform local clear screen function.
  1241. ;
  1242. loc_scrn       PROC near
  1243.  
  1244.            mov  cx,0
  1245.            mov  ax,0700h             ;clear the screen
  1246.            mov  dx,184fh
  1247.            mov  bx,0700h
  1248.            pushf
  1249.            call old_int10
  1250.            mov  ah,2             ;home the cursor
  1251.            mov  dx,0
  1252.            mov  bx,0
  1253.            pushf
  1254.            call old_int10
  1255.            ret
  1256.  
  1257. loc_scrn       ENDP
  1258. ;
  1259. ; Give caller online sys/op privledges.
  1260. ;
  1261. loc_sysop      PROC near
  1262.  
  1263.            mov  si,OFFSET sysop_msg
  1264.            call con_puts
  1265.            mov  cstat,0FFFFh         ;caller status byte
  1266.            ret
  1267.  
  1268. loc_sysop      ENDP
  1269. ;
  1270. ; Display caller name buffer locally.
  1271. ;
  1272. loc_caller     PROC near
  1273.  
  1274.            mov  bl,int10_merge
  1275.            mov  int10_merge,NULL
  1276.            mov  si,OFFSET caller_msg
  1277.            call con_puts
  1278.            mov  si,OFFSET namebuf
  1279.            call con_puts
  1280.            mov  al,']'
  1281.            call con_putc
  1282.            mov  int10_merge,bl
  1283.            ret
  1284.  
  1285. loc_caller     ENDP
  1286. ;
  1287. ;
  1288.            PAGE
  1289.            SUBTTL     *** RS232 Service Routines ***
  1290. ;---RS232-INTERRUPT-SERVICE-ROUTINES------------------------------------
  1291. ;  This is the interrupt main service routine for the serial port.
  1292. ; This routine is called due to one of the following occurances:
  1293. ;
  1294. ;  Priority:   (1) Received Data register has character.
  1295. ;           (2) Transmitter Holding register empty (Not Used Yet!).
  1296. ;           (3) Change in modem CD status (Carrier Detect).
  1297. ;
  1298. ; When the interrupt occurs the interrupt identification register is
  1299. ; read to check for which class of interrupt occured and call the
  1300. ; appropriate function to handle the request. Note that more than one
  1301. ; interrupt may have occured at once and the interrupt id register
  1302. ; must be checked for any pending interrupts before exiting.
  1303. ;-----------------------------------------------------------------------
  1304. ;
  1305. rs232_serv     PROC far
  1306.  
  1307.            sti            ;restart interrupts first!
  1308.            push ax            ;save registers
  1309.            push bx
  1310.            push cx
  1311.            push dx
  1312.            push di
  1313.            push si
  1314.            push ds
  1315.  
  1316.            mov  ax,cs        ;DS=CS
  1317.            mov  ds,ax
  1318. ;
  1319. ;  Check the 8259 interrupt controller for any other interrupts that
  1320. ; may be pending. More than one may have occured at same time!
  1321. ;
  1322. rs232_serv0:   mov  dx,PORT_BASE+2    ;interrupt id register
  1323.            in   al,dx        ;read interrupt id code
  1324.            test al,1        ;test for interrupts pending
  1325.            jnz  rs232_exit        ;no more to service, exit!
  1326.            mov  bl,al        ;set table index in lsb
  1327.            xor  bh,bh        ;clear the msb
  1328.            call cs:rs232_jmp[bx]    ;call appropriate service rtn
  1329.            jmp  SHORT rs232_serv0    ;check for other pending ints
  1330. ;
  1331. ;  Signal the 8259 interrupt controller that we are done.
  1332. ;
  1333. rs232_exit:    cli            ;halt interrupts temporarily
  1334.            mov  al,EOI        ;send EOI command to the
  1335.            out  IO_8259,al        ; 8259 interrupt controller.
  1336.            sti            ;now re-enable interrupts
  1337.            cmp  pause_req,NULL    ;Ctrl-S pause requested?
  1338.            je   rs232_exit1     ; no, exit from interrupt.
  1339.            cmp  pause_flg,NULL    ;Is pause already in effect?
  1340.            jne  rs232_exit1     ; yes, exit from interrupt.
  1341.            call pause_rtn        ;fall into pause loop until
  1342.                     ;another rx interrupt occurs.
  1343. rs232_exit1:   pop  ds
  1344.            pop  si
  1345.            pop  di
  1346.            pop  dx
  1347.            pop  cx
  1348.            pop  bx
  1349.            pop  ax
  1350.            iret
  1351.  
  1352. rs232_serv     ENDP
  1353. ;
  1354. ;  Jump table of routines to call on interrupt request
  1355. ;
  1356. rs232_jmp      dw OFFSET stat_serv    ;service modem status change
  1357.            dw OFFSET tx_serv    ;service tx-routine
  1358.            dw OFFSET rx_serv    ;service rx-routine
  1359. ;
  1360. ;
  1361. ;---PAUSE-ROUTINE-------------------------------------------------------
  1362. ; This routine handles the pause routines, generated by a Ctrl-S being
  1363. ; received at the serial port, if control key trapping is enabled.
  1364. ;-----------------------------------------------------------------------
  1365. ;
  1366. pause_rtn      PROC near
  1367.  
  1368.            mov  pause_flg,ON    ;signal pause in effect
  1369.            mov  ah,15
  1370.            int  10h         ;get video mode
  1371.            cmp  al,2        ;if CGA is found make sure
  1372.            je   vmode2        ; its enabled before pause
  1373.            cmp  al,3
  1374.            je   vmode3
  1375.            jmp  SHORT pause0    ;else, no re-enable needed.
  1376. vmode2:        mov  al,2Dh        ;re-enable value mode 2
  1377.            jmp  SHORT pause0
  1378. vmode3:        mov  al,29h        ;re-enable value mode 3
  1379.            mov  dx,3D8h        ;cga control register
  1380.            out  dx,al        ;send it to the cga
  1381. ;
  1382. ;  Now wait in a loop for another receive interrupt to occur or
  1383. ; for the timer to timeout and return control.
  1384. ;
  1385. pause0:        mov  cx,TIMEOUT*8    ;set up time out delay
  1386. pause1:        cmp  pause_req,NULL    ;has another interrupt occured
  1387.            je   pause_end        ; to cut off pause?
  1388. pause2:        cmp  tout_flg,NULL    ;any timeout?
  1389.            je   pause1        ; no,loop back
  1390.            mov  ax,2        ;else
  1391.            call timer        ; wait 1/9th sec
  1392.            loop pause1        ;loop if no timeout yet
  1393. pause_end:     mov  pause_req,NULL    ;reset pause request
  1394.            mov  pause_flg,NULL    ;pause no longer active
  1395.            ret
  1396.  
  1397. pause_rtn      ENDP
  1398. ;
  1399. ;
  1400. ;---RX-SERVICE-ROUTINE--------------------------------------------------
  1401. ; This routine is called every time a character arrives at the serial
  1402. ; port. The data is placed in the circular rx-queue and the buffer
  1403. ; pointers are incremented.
  1404. ;-----------------------------------------------------------------------
  1405. ;
  1406. rx_serv        PROC near
  1407.  
  1408.            mov  dx,PORT_BASE    ;rx-data register
  1409.            in   al,dx        ;get data from port
  1410.            mov  dx,PORT_BASE+5    ;line status register
  1411.            mov  bl,al        ;save character in BL
  1412.            in   al,dx        ;read line status register
  1413.            test ah,00011110b    ;receive error?
  1414.            jnz  rx_nerr        ;jmp if no rx-error
  1415.            mov  bl,0FBh        ;force error to 'check' char
  1416. rx_nerr:       mov  al,bl        ;restore char from BL
  1417. ;
  1418. ; The character is in the AL reg now, check for special characters.
  1419. ;
  1420.            cmp  pause_req,NULL    ;if pause is off, skip
  1421.            je   rx_serva        ; pause reset,
  1422.            mov  pause_req,NULL    ;else, reset pause and
  1423.            ret            ; exit.
  1424. rx_serva:      cmp  trap_flg,NULL    ;dont trap any ctrl-chars if
  1425.            je   rx_serv0        ; trap is off.
  1426.  
  1427. rx_servb:      cmp  al,CTRL_C        ;check for ^C break.
  1428.            jne  rx_servc
  1429.            cmp  brk_flg,NULL    ;skip if break off
  1430.            je   rx_servd
  1431.            int  1Bh         ;issue a break program interrupt
  1432. rx_reset:      mov  rx_head,0        ;reset the rx queue
  1433.            mov  rx_tail,0
  1434.            mov  rx_cnt,0
  1435.            ret            ; and exit
  1436.  
  1437. rx_servc:      cmp  al,CTRL_S        ;check for ^S pause.
  1438.            jne  rx_serv0
  1439.            mov  pause_req,ON    ;set the pause request flag on
  1440. rx_servd:      ret            ; and exit
  1441. ;
  1442. ; Put the character in the rx-queue and adjust the queue pointers.
  1443. ;
  1444. rx_serv0:      mov  bx,rx_tail        ;get the end pointer
  1445.            mov  [rx_buf+bx],al    ;put char in the queue
  1446.            inc  rx_cnt        ;inc cnt for char added
  1447.            inc  bx            ;advance the pointer
  1448.            cmp  bx,RX_BUFF        ;wrapped around yet?
  1449.            jl   rx_serv1
  1450.            mov  bx,0        ;yes, wrap around
  1451. rx_serv1:      cmp  bx,rx_head        ;is the buffer full?
  1452.            je   rx_serv3        ;yes, next char overwrites
  1453.            mov  rx_tail,bx        ;new end of queue
  1454.            ret
  1455. rx_serv3:
  1456.          IF USE_RTS
  1457.            mov  rts_flg,OFF     ;set flg signaling RTS is off
  1458.            mov  ax,OFF
  1459.            call port_rts        ;now drop the RTS line
  1460.          ELSE
  1461.            jmp  SHORT rx_reset
  1462.          ENDIF
  1463. rx_serv_end:   ret
  1464.  
  1465. rx_serv        ENDP
  1466. ;
  1467. ;
  1468. ;---TX-SERVICE-ROUTINE--------------------------------------------------
  1469. ; DUMMY FUNCTION -- Tx-interrupts are not implemented yet!
  1470. ;-----------------------------------------------------------------------
  1471. ;
  1472. tx_serv        PROC near
  1473.  
  1474.            ret
  1475.  
  1476. tx_serv        ENDP
  1477. ;
  1478. ;
  1479. ;---STATUS-SERVICE-ROUTINE----------------------------------------------
  1480. ; This routine is called every time a change in modem status is found.
  1481. ; This routine checks for loss of carrier and resets if carrier is lost.
  1482. ;-----------------------------------------------------------------------
  1483. ;
  1484. stat_serv      PROC near
  1485.  
  1486.            call port_cd             ;CD pin pulled high?
  1487.            jc   stat_exit             ;jmp if CD found
  1488.            mov  cd_lost,YES          ;set carrier lost flg
  1489.            cmp  cd_check,NULL         ;checking CD status?
  1490.            je   stat_exit             ;no, exit
  1491.            mov  int10_merge,NULL         ;skip the modem
  1492.            mov  int16_merge,NULL         ;skip the keyboard
  1493.            mov  si,OFFSET lost_msg         ;show carrier lost message
  1494.            call con_puts
  1495.            mov  ax,OFF             ;turn off dtr/rts, hang up
  1496.            call port_dtr
  1497.            mov  ax,2             ;wait a second
  1498.            call delay             ;fall through and wboot
  1499.            call boot_sys             ;re-boot the system!
  1500. stat_exit:     ret
  1501.  
  1502. stat_serv      ENDP
  1503. ;
  1504. ;-----------------------------------------------------------------------
  1505. ;          *** END OF INTERRUPT SERVICE ROUTINES ***
  1506. ;-----------------------------------------------------------------------
  1507. ;
  1508. ;
  1509.            PAGE
  1510.            SUBTTL     *** Receive Data Routines ***
  1511. ;-RX-READY--------------------------------------------------------------
  1512. ;   Set the zero flag if the rx-queue is empty, else clear the zero
  1513. ; flag to indicate that data is available in the queue.
  1514. ;
  1515. ;     Return:    Zero Flag set   = NO data in queue.
  1516. ;            Zero Flag reset = data waiting in queue.
  1517. ;
  1518. ;-----------------------------------------------------------------------
  1519. ;
  1520. rx_ready       PROC near
  1521.  
  1522.            cli                 ;halt all interrupts
  1523.            push bx
  1524.            or   bl,bl             ;clear zero flag
  1525.            mov  bx,rx_head             ;fetch the pointers
  1526.            cmp  bx,rx_tail             ;if head=tail, no data!
  1527.            pop  bx
  1528.            sti                 ;restart interrupts
  1529.            ret
  1530.  
  1531. rx_ready       ENDP
  1532. ;
  1533. ;
  1534. ;-RX-GET-CHARACTER------------------------------------------------------
  1535. ;   Get a character from the rx-queue. If the character is not available
  1536. ; return an EOF to signal an error. (All other registers preserved)
  1537. ;
  1538. ;     Return:    AX = EOF if error.
  1539. ;            AL = Character received
  1540. ;            AH = NULL (scan codes not supported)
  1541. ;
  1542. ;-----------------------------------------------------------------------
  1543. ;
  1544. rx_getc        PROC near
  1545.  
  1546.            cli                 ;halt all interrupts
  1547.            push bx
  1548.            mov  ax,EOF             ;assume error
  1549.            mov  bx,rx_head             ;fetch the pointers
  1550.            cmp  bx,rx_tail             ;if head=tail, no data!
  1551.            je   rx_getc3             ;no, exit with eof
  1552.            mov  al,[rx_buf+bx]         ;get data from head ptr
  1553.            xor  ah,ah             ;clear the msb scan code
  1554.            dec  rx_cnt             ;dec cnt after removal
  1555.            inc  bx                 ;advance head ptr
  1556.            cmp  bx,RX_BUFF             ;wrapped around?
  1557.            jl   rx_getc2             ; no, update head ptr
  1558.            mov  bx,0             ; yes, wrap ptr around
  1559. rx_getc2:      mov  rx_head,bx             ;update the ptr
  1560. rx_getc3:      pop  bx                 ;restart interrupts
  1561.            sti
  1562.            ret
  1563.  
  1564. rx_getc        ENDP
  1565. ;
  1566. ;
  1567. ;-----------------------------------------------------------------------
  1568. ; RX FLUSH -- Empty all characters from the mdm receive port
  1569. ;-----------------------------------------------------------------------
  1570. ;
  1571. rx_flush       PROC near
  1572.  
  1573.            cli
  1574.            mov  rx_head,0             ;reset head pointer
  1575.            mov  rx_tail,0             ;reset tail pointer
  1576.            mov  rx_cnt,0             ;reset counter
  1577.            sti
  1578.            ret
  1579.  
  1580. rx_flush       ENDP
  1581. ;
  1582. ;
  1583. ;-----------------------------------------------------------------------
  1584. ; RX SIZE -- Return the number of characters in the rx-queue.
  1585. ;
  1586. ;   Return:  AX = Characters in rx-queue.
  1587. ;
  1588. ;-----------------------------------------------------------------------
  1589. ;
  1590. rx_size        PROC near
  1591.  
  1592.            cli
  1593.            mov  ax,rx_cnt             ;get the count
  1594.            sti
  1595.            ret
  1596.  
  1597. rx_size        ENDP
  1598. ;
  1599. ;
  1600.            PAGE
  1601.            SUBTTL     *** Transmit Data Routines ***
  1602. ;-----------------------------------------------------------------------
  1603. ; TX PUTS - This function transmits the buffer pointed to by the AX
  1604. ; register for CL bytes. AL & CL register destroyed, all others are
  1605. ; preserved. This function does not use nulls translation.
  1606. ;
  1607. ;    Entry:    DS:SI -- buffer to transmit
  1608. ;           CL    -- count of bytes to transmit
  1609. ;
  1610. ;-----------------------------------------------------------------------
  1611. ;
  1612. tx_puts        PROC near
  1613.  
  1614.            xor  ch,ch             ;clear the msb
  1615.            cld                 ;clear direction flag
  1616. tx_puts1:      lodsb                 ;get a byte from string
  1617.            call tx_putc             ;send the data
  1618.            loop tx_puts1
  1619.            ret
  1620.  
  1621. tx_puts        ENDP
  1622. ;
  1623. ;
  1624. ;-----------------------------------------------------------------------
  1625. ; MODEM TX CHARACTER -- Send a character to modem through com port.
  1626. ; If the character sent was a line feed (LF) and 'nulls' greater that 0,
  1627. ; then nulls are sent after the line feed. (All registers preserved)
  1628. ;
  1629. ;   Entry:     AL   - Character to send
  1630. ;
  1631. ;-----------------------------------------------------------------------
  1632. ;
  1633. tx_char        PROC near
  1634.  
  1635.            call tx_putc        ;now send the character
  1636.          IF USE_NULLS
  1637.            push cx
  1638.            mov  cl,nulls        ;get # of nulls to send
  1639.            xor  ch,ch        ;clear the msb
  1640.            or   cx,cx        ;check if for any nulls to tx
  1641.            jz   tx_char2        ;exit if nulls not in effect
  1642.            cmp  al,LF        ;send nulls if a line feed
  1643.            jne  tx_char2        ;no, skip over if not a LF
  1644.            push ax            ;save the data
  1645. tx_char1:      mov  al,0
  1646.            call tx_putc        ;send a null out
  1647.            loop tx_char1        ;loop until CX=0
  1648.            pop  ax
  1649. tx_char2:      pop  cx
  1650.          ENDIF
  1651.            ret
  1652.  
  1653. tx_char        ENDP
  1654. ;
  1655. ;
  1656. ;-----------------------------------------------------------------------
  1657. ; TRANSMIT CHARACTER -- Send a character to modem through com port.
  1658. ; All registers used are saved before sending the char. Note that in
  1659. ; order to transmit a byte, that DSR and CTS must be active.
  1660. ;
  1661. ;   Entry:     AL   - Character to send
  1662. ;
  1663. ;-----------------------------------------------------------------------
  1664. ;
  1665. tx_putc        PROC near
  1666.  
  1667.            push dx
  1668.            push ax
  1669.  
  1670.            mov  dx,PORT_BASE+6    ;modem status register
  1671. tx_putc1:      in   al,dx        ;read port status
  1672.            and  al,030h        ;check DSR & CTS
  1673.            jz   tx_putc1        ;loop until DSR & CTS
  1674.            dec  dx            ;line status register
  1675. tx_putc2:      in   al,dx        ;read port status
  1676.            and  al,20h        ;check tx hold reg empty
  1677.            jz   tx_putc2        ;loop until tx complete
  1678.            sub  dx,5        ;data port register
  1679.  
  1680.            pop  ax            ;recover data to send
  1681.            out  dx,al        ;send the character
  1682.            pop  dx            ;restore dx
  1683.            ret
  1684.  
  1685. tx_putc        ENDP
  1686. ;
  1687. ;
  1688.            PAGE
  1689.            SUBTTL     *** RS232 Port Control Routines ***
  1690. ;-----------------------------------------------------------------------
  1691. ; PORT CARRIER DETECT -- Read the modem CD pin from COM status port
  1692. ;
  1693. ;   Exit:      CARRY FLAG SET = Carrier Detect (CD) found
  1694. ;
  1695. ;-----------------------------------------------------------------------
  1696. ;
  1697. port_cd        PROC near
  1698.  
  1699.            push dx
  1700.            push ax
  1701.  
  1702.            cli
  1703.            mov  dx,PORT_BASE+6         ;mdm status register
  1704.            or   al,al             ;clear the carry flag
  1705.            in   al,dx             ;get the port status
  1706.            rcl  al,1             ;rotate left through carry
  1707.            sti
  1708.  
  1709.            pop  ax
  1710.            pop  dx
  1711.            ret
  1712.  
  1713. port_cd        ENDP
  1714. ;
  1715. ;
  1716. ;-----------------------------------------------------------------------
  1717. ; PORT DTR -- Toggle the DTR/RTS line to the modem
  1718. ;
  1719. ;   Entry:     AX == 0    DTR/RTS off
  1720. ;           AX <> 0    DTR/RTS on
  1721. ;
  1722. ;-----------------------------------------------------------------------
  1723. ;
  1724. port_dtr       PROC near
  1725.  
  1726.            push bx
  1727.            push dx
  1728.  
  1729.            cli
  1730.            mov  bx,ax        ;save state flag
  1731.            mov  dx,PORT_BASE+4    ;modem control register
  1732.            in   al,dx
  1733.            or   bx,0        ;turn on or off?
  1734.            jz   port_dtr0
  1735.            or   al,00000011b    ;DTR/RTS bits on
  1736.            jmp  SHORT port_dtr1
  1737. port_dtr0:     and  al,11111100b    ;DTR/RTS bits off
  1738. port_dtr1:     mov  dx,PORT_BASE+4    ;modem control register
  1739.            out  dx,al
  1740.            sti
  1741.  
  1742.            pop  dx
  1743.            pop  bx
  1744.            ret
  1745.  
  1746. port_dtr       ENDP
  1747. ;
  1748. ;
  1749. ;-----------------------------------------------------------------------
  1750. ; PORT RTS -- Toggle only the RTS line to the modem
  1751. ;
  1752. ;   Entry:     AX == 0 RTS off
  1753. ;           AX <> RTS on
  1754. ;
  1755. ;-----------------------------------------------------------------------
  1756. ;
  1757.          IF USE_RTS
  1758. port_rts       PROC near
  1759.  
  1760.            push bx
  1761.            push dx
  1762.  
  1763.            cli
  1764.            mov  bx,ax        ;save state flag
  1765.            mov  dx,PORT_BASE+4    ;modem control register
  1766.            in   al,dx
  1767.            or   bx,0        ;turn on or off?
  1768.            jz   port_rts0
  1769.            or   al,00000010b    ;RTS bits on
  1770.            jmp  SHORT port_rts1
  1771. port_rts0:     and  al,11111101b    ;RTS bits off
  1772. port_rts1:     mov  dx,PORT_BASE+4    ;modem control register
  1773.            out  dx,al
  1774.            sti
  1775.  
  1776.            pop  dx
  1777.            pop  bx
  1778.            ret
  1779.  
  1780. port_rts       ENDP
  1781.          ENDIF
  1782. ;
  1783. ;
  1784. ;-----------------------------------------------------------------------
  1785. ; ASYNC PORT BAUD RATE SET -- Set the baud rate of the 8250.
  1786. ;
  1787. ;  Entry: AX = Baud rate baud rate initialization value.
  1788. ;
  1789. ;-----------------------------------------------------------------------
  1790. ;
  1791. port_baud      PROC near
  1792.  
  1793.            push dx
  1794.  
  1795.            cli
  1796.            push ax
  1797.            mov  dx,PORT_BASE+3    ;line control register
  1798.            in   al,dx
  1799.            or   al,10000000b    ;set DLAB = 1
  1800.            out  dx,al
  1801.            pop  ax
  1802.            mov  dx,PORT_BASE
  1803.            out  dx,al        ;send the lsb
  1804.            inc  dx
  1805.            mov  al,ah
  1806.            out  dx,al        ;send the msb
  1807.  
  1808.            mov  dx,PORT_BASE+3    ;line control register
  1809.            in   al,dx
  1810.            and  al,not 10000000b    ;set DLAB = 0
  1811.            out  dx,al
  1812.            mov  al,00000011b    ;no parity, 8 bits, 1 stop bit
  1813.            out  dx,al
  1814.            sti
  1815.  
  1816.            pop  dx
  1817.            ret
  1818.  
  1819. port_baud      ENDP
  1820. ;
  1821. ;
  1822. ;-----------------------------------------------------------------------
  1823. ; ASYNC PORT INTERRUPT START -- Starts the interrupts from the 8250.
  1824. ; This routine sets up all the interrupt registers on the 8250 and
  1825. ; on the 8259 interrupt controller for interrupts. The default start
  1826. ; mode is for Rx/Tx interrupts only, modem status is enabled after
  1827. ; a caller is online to check for carrier detect lost.
  1828. ;-----------------------------------------------------------------------
  1829. ;
  1830. port_start     PROC near
  1831.  
  1832.            mov  dx,PORT_BASE+3    ;line control register
  1833.            in   al,dx
  1834.            and  al,not 10000000b    ;set DLAB = 0
  1835.            out  dx,al
  1836.            mov  dx,PORT_BASE    ;data holding register
  1837.            in   al,dx        ;flush any Rx-data out
  1838. ;
  1839. ; 1) Set the correct bit in the 8259 interrupt controller to enable
  1840. ;    the IRQ4 interrupts from the serial port.
  1841. ;
  1842.            pushf            ;save interrupt status
  1843.            cli            ;stop interrupts temporarily
  1844.            mov  cl,not IRQ_BASE    ;set the IRQ4 bit ON to 8259
  1845.            in   al,21h        ;read 8259 status
  1846.            and  al,cl        ;set bit to zero to enable
  1847.            out  21h,al        ;update new interrupt status
  1848. ;
  1849. ; 2) At base+3 cut off the DLAB bit to allow access to the
  1850. ;    interrupt enable register (EIR).
  1851. ;
  1852.            mov  dx,PORT_BASE+3
  1853.            in   al,dx        ;read current status
  1854.            and  al,not 10000000b
  1855.            out  dx,al        ;turn off DLAB
  1856. ;
  1857. ; 3) At base base+1 (IER), enable interrupts to the 8250
  1858. ;
  1859.            mov  dx,PORT_BASE+1    ;8250 interrupt enable register
  1860.            mov  al,00000000b    ;enable rx interrupts to start
  1861.            out  dx,al
  1862. ;
  1863. ; 4) At base base+4 (mdm control), enable OUT2 signal
  1864. ;
  1865.            mov  dx,PORT_BASE+4    ;modem control register
  1866.            in   al,dx
  1867.            or   al,00001000b    ;set the out2 bit
  1868.            out  dx,al        ;send update
  1869.            popf            ;restore interrupt status
  1870. ;
  1871. ; Interrupts are enabled and will load the first character ready
  1872. ;
  1873.            call clear_pints     ;clear any pending interrupts
  1874.            ret
  1875.  
  1876. port_start     ENDP
  1877. ;
  1878. ;
  1879. ;-----------------------------------------------------------------------
  1880. ; ASYNC PORT INTERRUPT STOP -- Stops the interrupts from the 8250.
  1881. ; This routine resets all the interrupt registers on the 8250 and
  1882. ; on the 8259 interrupt controller.
  1883. ;-----------------------------------------------------------------------
  1884. ;
  1885. port_stop      PROC near
  1886.  
  1887. ;
  1888. ; 1) Set the correct bit in the 8259 interrupt controller to disable
  1889. ;    the IRQ4 interrupts from the serial port.
  1890. ;
  1891.            pushf            ;save interrupt status
  1892.            cli            ;stop interrupts temporarily
  1893.            mov  cl,00010000b    ;set the IRQ4 bit OFF to 8259
  1894.            in   al,21h        ;read 8259 status
  1895.            or   al,cl        ;set bit to 'one' to disable
  1896.            out  21h,al        ;update new interrupt status
  1897. ;
  1898. ; 2) At base+3 cut off the DLAB bit to allow access to the
  1899. ;    interrupt enable register (EIR).
  1900. ;
  1901.            mov  dx,PORT_BASE+3
  1902.            in   al,dx        ;read current status
  1903.            and  al,not 10000000b
  1904.            out  dx,al        ;turn off DLAB
  1905. ;
  1906. ; 3) At base base+1 (IER), disable interrupts to the 8250
  1907. ;
  1908.            mov  dx,PORT_BASE+1     ;8250 interrupt enable register
  1909.            mov  al,00000000b     ;disable all interrupts
  1910.            out  dx,al
  1911. ;
  1912. ; 4) At base base+4 (mdm control), disable OUT2 signal
  1913. ;
  1914.            mov  dx,PORT_BASE+4     ;modem control register
  1915.            in   al,dx
  1916.            and  al,not IRQ_BASE     ;reset the out2 bit
  1917.            out  dx,al         ;send update
  1918.            popf            ;restore interrupt status
  1919.            ret
  1920.  
  1921. port_stop      ENDP
  1922. ;
  1923. ;
  1924. ;-----------------------------------------------------------------------
  1925. ; ASYNC INTERRUPT MODE -- This routine sets the interrupts modes for
  1926. ; the comm port either on or off.
  1927. ;
  1928. ;  Entry:
  1929. ;
  1930. ;   AL = Mode (0=OFF, 1=ON)
  1931. ;
  1932. ;   AH = 0 -- Set the Rx-Interrupt mode
  1933. ;   AH = 1 -- Set the Tx-Interrupt mode
  1934. ;   AH = 2 -- Set the Modem Status Interrupt mode
  1935. ;
  1936. ;-----------------------------------------------------------------------
  1937. ;
  1938. port_imode     PROC near
  1939.  
  1940.            push ax
  1941.            push bx
  1942.            push cx
  1943.            pushf            ;save interrupt status
  1944.            cli            ;stop interrupts temporarily
  1945.  
  1946.            mov  bl,al
  1947.            or   ah,ah
  1948.            mov  bh,00000001b
  1949.            jz   imode0          ;rx-interrupts?
  1950.            dec  ah
  1951.            mov  bh,00000010b
  1952.            jz   imode0          ;tx-interrupt?
  1953.            dec  ah
  1954.            mov  bh,00001000b
  1955.            jz   imode0          ;modem status interrupts?
  1956.            jmp  SHORT imode_end
  1957. ;
  1958. ; 1) At base+3 cut off the DLAB bit to allow access to the
  1959. ;    interrupt enable register (EIR).
  1960. ;
  1961. imode0:        mov  dx,PORT_BASE+3
  1962.            in   al,dx        ;read current status
  1963.            and  al,not 10000000b
  1964.            out  dx,al        ;turn off DLAB
  1965. ;
  1966. ; 2) At base base+1 (IER), set interrupts to the 8250
  1967. ;
  1968.            mov  dx,PORT_BASE+1    ;8250 interrupt enable register
  1969.            in   al,dx        ;read current interrupt state
  1970.            or   bl,bl        ;test for on/off flag
  1971.            jnz  imode1
  1972.            not  bh            ;set the bit off
  1973.            and  al,bh
  1974.            jmp  SHORT imode2
  1975. imode1:        or   al,bh        ;set the bit on
  1976. imode2:        out  dx,al        ;send new interrupt mode
  1977.  
  1978. imode_end:     popf            ;restart interrupts
  1979.            pop  cx
  1980.            pop  bx
  1981.            pop  ax
  1982.            ret
  1983.  
  1984. port_imode   ENDP
  1985. ;
  1986. ;
  1987. ;-----------------------------------------------------------------------
  1988. ; CLEAR PENDING INTERRUPTS -- Clear any pending interrupts from the
  1989. ; 8250 and the 8259 interrupt controller.
  1990. ;-----------------------------------------------------------------------
  1991. ;
  1992. clear_pints    PROC near
  1993.  
  1994.            mov  dx,PORT_BASE+2    ;(IIR) interrupt id register
  1995.            in   al,dx
  1996.            test al,1
  1997.            jnz  clear_exit        ;exit if none pending
  1998.            xor  bh,bh
  1999.            mov  bl,al
  2000.            call cs:clr_jmp[bx]    ;clear the interrupt
  2001.            jmp  SHORT clear_pints
  2002. clear_exit:    ret
  2003. ;
  2004. ;  Jump table of routines to call clear interrupts
  2005. ;
  2006. clr_jmp        dw OFFSET clr_stat    ;clear modem status
  2007.            dw OFFSET clr_tx     ;clear tx-routine
  2008.            dw OFFSET clr_rx     ;clear rx-routine
  2009. ;
  2010. ; Clear the interrupt based on the interrupt id code
  2011. ;
  2012. clr_stat:      mov  dx,PORT_BASE+6    ;cleared by reading
  2013.            in   al,dx        ; modem status reg.
  2014.            ret
  2015.  
  2016. clr_tx:        ret            ;cleared from reading IIR
  2017.  
  2018. clr_rx:        mov  dx,PORT_BASE    ;cleared by reading rx-data
  2019.            in   al,dx        ; register.
  2020.            ret
  2021.  
  2022. clear_pints    ENDP
  2023. ;
  2024. ;
  2025.            PAGE
  2026.            SUBTTL     *** Utility Routines ***
  2027. ;----------------------------------------------------------------------
  2028. ;    *** These routines compliments of William C. Bryan ***
  2029. ;
  2030. ;   This routine has two entry points. One entry point allows timing
  2031. ; in 18ths of seconds, and the other entry point allows in seconds.
  2032. ;----------------------------------------------------------------------
  2033. ;
  2034. ; TIMER -- provides a hardware delay timing in 18ths of a second
  2035. ;
  2036. ;    Entry:    AX = # of 1/18th seconds to delay (65535 Max)
  2037. ;
  2038. ;----------------------------------------------------------------------
  2039. ;
  2040. ; DELAY -- provides a hardware delay timing in seconds
  2041. ;
  2042. ;    Entry:    AX = # of seconds to delay.   (60 Minutes Max)
  2043. ;
  2044. ;----------------------------------------------------------------------
  2045. ;
  2046. timer           PROC near
  2047.  
  2048.            push ax           ;save all registers changed
  2049.            push bx
  2050.            push cx
  2051.            push dx
  2052.  
  2053. begin:           call getticks       ;read present time into DX
  2054.            add  dx,ax
  2055.            adc  cx,0
  2056.            cmp  cx,018h       ;check for 24 hour rollover
  2057.            jl   timer0
  2058.            cmp  dx,0B0h
  2059.            jl   timer0
  2060.            sub  dx,0B0h       ;correct for rollover
  2061.            sbb  cx,018h
  2062. timer0:        mov  bx,dx       ;AX:BX = Match time
  2063.            mov  ax,cx
  2064. timer1:        call getticks
  2065.            cmp  dx,bx       ;compare match time to current time
  2066.            jne  timer1       ; as a long value
  2067.            cmp  cx,ax
  2068.            jne  timer1
  2069.  
  2070.            pop  dx           ;restore altered registers
  2071.            pop  cx
  2072.            pop  bx
  2073.            pop  ax
  2074.            ret
  2075.  
  2076. delay           LABEL near
  2077.  
  2078.            push ax           ;save all registers changed
  2079.            push bx
  2080.            push cx
  2081.            push dx
  2082.  
  2083.            mov  cx,ax       ;provide correction for 18.2 ms timing
  2084.            mov  ax,182       ;TICKRATE = 18.2 times per second / 10
  2085.            mul  cx           ;multiply CX * TICKRATE
  2086.            mov  cx,10
  2087.            div  cx           ;now divide by ten, final value in AX
  2088.            jmp  SHORT begin
  2089.  
  2090. timer           ENDP
  2091. ;
  2092. ;
  2093. ;----------------------------------------------------------------------
  2094. ; GETTICKS -- get the current BIOS clock ticks value and return
  2095. ;          long value in the DX:CX register.
  2096. ;----------------------------------------------------------------------
  2097. ;
  2098. getticks       PROC near
  2099.  
  2100.            push ax            ;save ax reg
  2101.            xor  ah,ah
  2102.            int  1Ah         ;read time of day
  2103.            pop  ax            ;restore ax
  2104.            ret
  2105.  
  2106. getticks       ENDP
  2107. ;
  2108. ;
  2109. ;----------------------------------------------------------------------
  2110. ; BEEP -- Emit a tone for 'BL' durations of ~500ms each.
  2111. ;----------------------------------------------------------------------
  2112. ;
  2113. beep           PROC near
  2114.  
  2115.            push ax
  2116.            push cx
  2117.            mov  al,10110110B         ;timer mode2, lsb,msb,bin
  2118.            out  PORT_TM+3,al         ;write to timer mode reg
  2119.            mov  ax,533h             ;divisor for 1000hz
  2120.            out  PORT_TM+2,al         ;write timer 2 cnt, lsb.
  2121.            mov  al,ah
  2122.            out  PORT_TM+2,al         ;write timer 2 cnt, msb.
  2123.            in   al,PORT_PB             ;read port setting
  2124.            mov  ah,al             ;save port register
  2125.            or   al,3             ;turn on the speaker
  2126.            out  PORT_PB,al
  2127.            sub  cx,cx
  2128. beep1:
  2129.            loop beep1             ;delay loop
  2130.            dec  bl
  2131.            jnz  beep1             ;loop until BL = 0
  2132.            mov  al,ah             ;recover port state
  2133.            out  PORT_PB,al             ;restore port state
  2134.            pop  cx
  2135.            pop  ax
  2136.            ret
  2137.  
  2138. beep           ENDP
  2139. ;
  2140. ;
  2141. ;-----------------------------------------------------------------------
  2142. ; CONSOLE PUT CHARACTER -- Print a character on the console and remote.
  2143. ;
  2144. ;   Entry:     AL   - Character to Print locally and remote
  2145. ;
  2146. ;-----------------------------------------------------------------------
  2147. ;
  2148. con_putc       PROC near
  2149.  
  2150.            mov  ah,0Eh        ;write tty function
  2151.            int  10h         ;video bios int
  2152.            ret
  2153.  
  2154. con_putc       ENDP
  2155. ;
  2156. ;
  2157. ;-----------------------------------------------------------------------
  2158. ; CONSOLE PUT STRING -- Send the console a string at DS:DI. The string
  2159. ; must contain a "$" or null character to signal the end of the string.
  2160. ; If 'int10_skip' is non-zero, characters will not be sent to the modem.
  2161. ;
  2162. ;   Entry:     DS:SI - Points to the string of chars to send
  2163. ;
  2164. ;-----------------------------------------------------------------------
  2165. ;
  2166. con_puts       PROC  near
  2167.  
  2168.            push  ax
  2169.            cld
  2170. con_puts1:     lodsb            ;get a byte from string
  2171.            cmp  al,'$'        ;if '$', end of string
  2172.            je   con_puts2
  2173.            cmp  al,0        ;if null, end of string
  2174.            je   con_puts2
  2175.            mov  ah,0Eh        ;write tty function
  2176.            int  10h         ;video bios int
  2177.            jmp  SHORT con_puts1    ;continue looping
  2178. con_puts2:     pop  ax
  2179.            ret
  2180.  
  2181. con_puts       ENDP
  2182. ;
  2183. ;
  2184. ; -- All code after this point is trashed after loading --
  2185. ;
  2186. end_resident:
  2187. ;
  2188.            PAGE
  2189.            SUBTTL     *** Initialization and Loader Routines ***
  2190. ;
  2191. ;-----------------------------------------------------------------------
  2192. ;--------------------- Start of Loader Code ----------------------------
  2193. ;-----------------------------------------------------------------------
  2194. ;
  2195. ;   NOTE: All code after this point is trashed after the connection
  2196. ;      to remote station is established.
  2197. ;
  2198. ;-----------------------------------------------------------------------
  2199. ;
  2200. init_msg       db 0Dh,0Ah
  2201.            db "BYE-PC for the IBM Personal Computer - Version "
  2202.            db PGM_VER+'0',".0",PGM_REV+'0',0Dh,0Ah
  2203.            db "Copyright (C) MCODE Software 1986, 1987. All rights reserved", 0Dh,0Ah
  2204.            db "[Local Control use Ctrl-C]"
  2205.          IFE SMART_MDM
  2206.            db 0Dh,0Ah,0Dh,0Ah,"Waiting for call...$"
  2207.          ELSE
  2208.            db 0Dh,0Ah,0Dh,0Ah,"$"
  2209.          ENDIF
  2210.  
  2211. halt_msg       db 0Dh,0Ah
  2212.          IFE SMART_MDM
  2213.            db 0Dh,0Ah
  2214.          ENDIF
  2215.          IF LOGON_EXE
  2216.            db "PRESS: <E>xecute locally",0Dh,0Ah
  2217.            db "       <R>esume Call Wait",0Dh,0Ah
  2218.          ELSE
  2219.            db "PRESS: <R>esume Call Wait",0Dh,0Ah
  2220.          ENDIF
  2221.            db "       Return",17,196,217," exit to DOS$"
  2222.  
  2223. exit_msg       db 0Dh,0Ah,0Dh,0Ah
  2224.            db "Exiting BYE-PC...."
  2225.            db 0Dh,0Ah, "$"
  2226.  
  2227. bye_msg        db 0Dh,0Ah
  2228.            db "  Goodbye, call again...."
  2229.            db 0Dh,0Ah,0Dh,0Ah, "$"
  2230.  
  2231. crlf           db 0Dh,0Ah,"$"
  2232.  
  2233. mdm_nulls      db 0Dh,0Ah
  2234.            db "Nulls, if needed, (0-9)? ","$"
  2235.  
  2236. mdm_flunk      db 0Dh,0Ah,0Dh,0Ah
  2237.            db "You flunked the (0-9) IQ test...Bye!"
  2238.            db 0Dh,0Ah,0Dh,0Ah, "$"
  2239.  
  2240.          IF SMART_MDM
  2241. error_msg1     db 0Dh,0Ah
  2242.            db "[ERROR: Modem Initialization!]",0Dh,0Ah
  2243.            db "$"
  2244.          ENDIF
  2245.  
  2246.          IF LOGON_EXE
  2247. free_err_msg   db 0Dh,0Ah
  2248.            db "[ERROR: Releasing Memory!]",0Dh,0Ah
  2249.            db 0Dh,0Ah,0Dh,0Ah, "$"
  2250.  
  2251. exec_err_msg   db 0Dh,0Ah
  2252.            db "[ERROR: Executing .COM or .EXE file!]",0Dh,0Ah
  2253.            db 0Dh,0Ah,0Dh,0Ah, "$"
  2254.          ENDIF
  2255.  
  2256.          IF SMART_MDM
  2257. mdm_init       db "ATE0F1Q0V0M0"
  2258.          IF BPS_2400
  2259.            db "X2"
  2260.          ELSE
  2261.            db "X1"
  2262.          ENDIF
  2263.            db "S0=0S2=3S10=25"
  2264.          ENDIF
  2265.          IF TELEBIT
  2266.            db "S50=0S51=4S52=1S53=1S55=2S58=2S66=1S68=2"
  2267.          ENDIF
  2268.            db 0Dh,0Ah,"$"
  2269.  
  2270.          IF SMART_MDM
  2271. mdm_reset      db "ATZ",0Dh,0Ah,"$"
  2272. mdm_atten      db "AT",0Dh,0Ah,"$"
  2273. mdm_answer     db "ATA",0Dh,0Ah,"$"
  2274. mdm_noanswer   db "ATS0=0",0Dh,0Ah,"$"
  2275.          ENDIF
  2276.  
  2277. msg_nocd       db 0Dh,0Ah
  2278.            db "[No Carrier]"
  2279.            db 0Dh,0Ah,"$"
  2280.  
  2281. msg_300        db "[300 bps]",0Dh,"$"
  2282.  
  2283.          IF BPS_1200 OR BPS_2400 OR TELEBIT
  2284. msg_1200       db "[1200bps]",0Dh,"$"
  2285.          ENDIF
  2286.  
  2287.          IF BPS_2400 OR TELEBIT
  2288. msg_2400       db "[2400bps]",0Dh,"$"
  2289.          ENDIF
  2290.  
  2291.          IF TELEBIT
  2292. msg_tbit       db "[Highspeed PEP]",0Dh,"$"
  2293.          ENDIF
  2294. ;
  2295. locl_flg       db   NO            ;local control flag
  2296. res_buf        db   16 dup(0)        ;modem results code buffer
  2297. ;
  2298. ;
  2299.            PAGE
  2300. ;-----------------------------------------------------------------------
  2301. ;           Load and Initialize the Program
  2302. ;-----------------------------------------------------------------------
  2303. ; INITIALIZE check to see if BYE-PC is already installed. If it is,
  2304. ; hangup the modem and re-boot for the next call. Otherwise, store all
  2305. ; of the interrupts present locations, setup rs232 interrupt vector and
  2306. ; intialize the modem and wait for a call.
  2307. ;
  2308. ;   NOTE: All subroutines after this point may not be called from
  2309. ;      above this point, as they are discarded after loading.
  2310. ;
  2311. ;-----------------------------------------------------------------------
  2312. ;
  2313. initialize     PROC near
  2314.  
  2315.            mov  ax,cs             ;DS = CS
  2316.            mov  ds,ax
  2317. ;
  2318. ; check for BYE already active.
  2319. ;
  2320.            mov  ax,3516h             ;get vector
  2321.            int  21h
  2322.            cmp  es:bye_sign,1234h         ;bye signiture
  2323.            jne  load_bye             ;bye not present, load it
  2324. ;
  2325. ; Bye is already loaded, say goodby, hangup, and re-boot system
  2326. ;
  2327.            mov  ah,INT_STAT          ;mdm status interrupts.
  2328.            mov  al,OFF             ;turn off status ints
  2329.            call port_imode             ; for loss of carrier.
  2330.            mov  si,OFFSET bye_msg         ;send goodbye message
  2331.            call con_puts             ; to console and mdm.
  2332.            mov  ax,OFF             ;hang up the modem.
  2333.            call port_dtr
  2334.            mov  ax,2             ;wait a sec or two
  2335.            call delay
  2336.            mov  ax,ON             ;turn dtr back on
  2337.            call port_dtr
  2338.          IF SMART_MDM
  2339.            mov  si,OFFSET mdm_noanswer   ;tell the mdm to not
  2340.            call mdm_puts             ; answer any calls
  2341.          ENDIF
  2342.            mov  ax,2             ;wait a sec or two
  2343.            call delay
  2344.  
  2345.            ASSUME ds:rom_bios_data         ;boot the system
  2346. wboot_sys:     mov  ax,rom_bios_data         ;set DS to rom bios data
  2347.            mov  ds,ax             ; area.
  2348.            mov  reset_flag, 1234h         ;set the alt-ctrl-del flag.
  2349.            db   0EAH             ;jmp to the specified:
  2350.            dw   WBOOT_OFF             ; OFFSET
  2351.            dw   WBOOT_SEG             ; segment
  2352.            ASSUME ds:code
  2353. ;
  2354. ; Wait for call re-vector interrupts to BYE intercept routines
  2355. ;
  2356. load_bye:      mov  ah,25h              ;set rs232 vector
  2357.            mov  al,RS232_INT
  2358.            mov  dx, OFFSET rs232_serv      ;set new rs232 int
  2359.            int  21h               ;make dos call
  2360.  
  2361.            mov  ax,3509h              ;dos get vector function
  2362.            int  21h               ;make dos call
  2363.            mov  WORD PTR [old_int09],bx      ;set asside old vector to
  2364.            mov  WORD PTR [old_int09 + 2],es   ; allow pass to Bios    L
  2365.  
  2366.            mov  ax,3510h              ;dos get vector function
  2367.            int  21h               ;make dos call
  2368.            mov  WORD PTR [old_int10],bx      ;set asside old vector to
  2369.            mov  WORD PTR [old_int10 + 2],es   ; allow pass to Bios
  2370.  
  2371.            mov  ax,3513h              ;dos get vector function
  2372.            int  21h               ;make dos call
  2373.            mov  WORD PTR [old_int13],bx      ;set asside old vector to
  2374.            mov  WORD PTR [old_int13 + 2],es   ; allow pass to Bios
  2375.  
  2376.            mov  ax,3516h              ;dos get vector function
  2377.            int  21h               ;make dos call
  2378.            mov  WORD PTR [old_int16],bx      ;set asside old vector to
  2379.            mov  WORD PTR [old_int16 + 2],es   ; allow pass to Bios
  2380.  
  2381.            mov  ax,351Ch              ;dos get vector function
  2382.            int  21h               ;make dos call
  2383.            mov  WORD PTR [old_int1C],bx      ;set asside old vector to
  2384.            mov  WORD PTR [old_int1C + 2],es   ; allow pass to Bios
  2385. ;
  2386. ; Wait for a call, then replace the interrupt vectors with the new ones.
  2387. ;
  2388.            call call_wait              ;wait for a call
  2389.  
  2390.            mov  ax,2509h              ;dos set vector function
  2391.            mov  dx, OFFSET int09_main      ;set new keybd int
  2392.            int  21h               ;make dos call
  2393.  
  2394.            mov  ax,2510h              ;dos set vector function
  2395.            mov  dx, OFFSET int10_main      ;set new video int
  2396.            int  21h               ;make dos call
  2397.  
  2398.            mov  ax,2513h              ;dos set vector function
  2399.            mov  dx, OFFSET int13_main      ;set new disk int
  2400.            int  21h               ;make dos call
  2401.  
  2402.            mov  ax,2516h              ;dos set vector function
  2403.            mov  dx, OFFSET int16_main      ;set new keyboard int
  2404.            int  21h               ;make dos call
  2405.  
  2406.            mov  ax,251Ch              ;dos set vector function
  2407.            mov  dx, OFFSET int1C_main      ;set up timer tick int
  2408.            int  21h               ;make dos call
  2409.  
  2410.            mov  ax,2566h              ;dos set vector function
  2411.            mov  dx, OFFSET int66_main      ;set BYE control int
  2412.            int  21h               ;make dos call
  2413. ;
  2414. ; Execute .EXE/.COM file upon after modem is logged on
  2415. ;
  2416.            mov  trap_flg,ON           ;enable ^S & ^C trapping
  2417.          IF LOGON_EXE
  2418.            cmp  locl_flg,NULL          ;if local, cut of mdm
  2419.            je   run_local              ; to screen & keybd.
  2420.            mov  int10_merge,NULL          ;data 'to' mdm off
  2421.            mov  int16_merge,NULL          ;data 'from' mdm off
  2422. run_local:     mov  brk_flg,NULL          ;disable remote Ctrl-C
  2423.            call free_mem              ;free memory after loader
  2424.            call exec_pgm              ;run external program
  2425.          ENDIF
  2426. ;
  2427. ; Calculate the size of the program and load resident portion.
  2428. ;
  2429.          IF REBOOT
  2430.            cmp  locl_flg,NULL          ;if local re-boot
  2431.            je   run_local1
  2432.            mov  ax,2              ;wait a couple secs
  2433.            call delay
  2434.            jmp  wboot_sys
  2435.          ENDIF
  2436.  
  2437. run_local1:    mov  dx,OFFSET end_resident      ;get end of program area.
  2438.            mov  cl,4              ;resident cant do with an
  2439.            shr  dx,cl              ; expression because assembler
  2440.            inc  dx                  ; can't calc w/relocatable label.
  2441.            mov  ax,3100h              ;dos make resident function.
  2442.            int  21h               ;terminate be stay resident.
  2443.  
  2444. initialize     ENDP
  2445. ;
  2446. ;
  2447.            PAGE
  2448. ;-----------------------------------------------------------------------
  2449. ; CALL WAIT -- clears the screen, re-initializes the modem and watches
  2450. ; the modem for any calls. When a call is detected, the modem answers
  2451. ; and the program determines the baud rate of the call. If nulls are
  2452. ; enabled, the caller is prompted for the number of nulls before comp-
  2453. ; leting the connection.
  2454. ;-----------------------------------------------------------------------
  2455. ;
  2456. call_wait      PROC near
  2457. ;
  2458. ; Initialize baud rate, turn on DTR/RTS, and start interrupts
  2459. ;
  2460.          IF BPS_300
  2461.            mov  ax,BPS300             ;start at 300 bps
  2462.          ENDIF
  2463.          IF BPS_1200
  2464.            mov  ax,BPS1200             ;start at 1200 bps
  2465.          ENDIF
  2466.          IF BPS_2400
  2467.            mov  ax,BPS2400             ;start at 2400 bps
  2468.          ENDIF
  2469.          IF TELEBIT
  2470.            mov  ax,BPS9600             ;start at 9600 bps
  2471.          ENDIF
  2472.            call port_baud             ;initialize com port
  2473.            mov  ax,ON             ;turn on dtr/rts
  2474.            call port_dtr             ; and IRQ line.
  2475.            call port_start             ;enable interrupts
  2476.            mov  al,ON
  2477.            mov  ah,INT_RX             ;start Rx-interrupts
  2478.            call port_imode
  2479.  
  2480. call_restart:  mov  cx,0
  2481.            mov  ax,0700h             ;clear the screen
  2482.            mov  dx,184fh
  2483.            mov  bx,0700h
  2484.            int  10h
  2485.            mov  ah,2             ;home the cursor
  2486.            mov  dx,0
  2487.            mov  bx,0
  2488.            int  10h
  2489.            mov  si,OFFSET init_msg         ;show sign on message
  2490.            call con_puts
  2491. ;
  2492. ; Reset and initialize the modem for a phone call.
  2493. ;
  2494.          IF SMART_MDM
  2495.            mov  si,OFFSET mdm_reset      ;reset the modem
  2496.            call mcon_puts             ;send the 'ATZ'
  2497.            mov  ax,2             ;wait for 2 seconds
  2498.            call delay             ;wait for delay time
  2499.            call rx_flush             ;empty trash from Rx buf
  2500.            mov  si,OFFSET mdm_init         ;initialization string
  2501.            call mcon_puts
  2502.            mov  ax,1             ;wait for 1 second
  2503.            call delay
  2504.            call rx_flush             ;empty trash from Rx buf
  2505.            mov  si,OFFSET mdm_atten      ;try to get mdm's attention
  2506.            call mdm_puts
  2507.  
  2508. reset0:        call rx_ready             ;any data ready?
  2509.            jz   reset0             ;no char waiting
  2510.            call rx_getc             ;is the modem setup ok
  2511.            cmp  al,'0'
  2512.            je   reset1
  2513.            mov  si,OFFSET error_msg1     ;did'nt get back an Ok
  2514.            call con_puts             ; result code of 0.
  2515.            mov  al,BELL             ;ring the bell
  2516.            call con_putc
  2517.            mov  ax,2             ;wait 2 seconds
  2518.            call delay
  2519.            jmp  call_restart         ;try again...
  2520.  
  2521. reset1:        call con_putc             ;show init complete ok
  2522.            mov  si,OFFSET crlf
  2523.            call con_puts
  2524.            call rx_flush             ;empty trash from Rx buf
  2525.          ENDIF
  2526. ;
  2527. ; Wait for modem to ring or a Ctrl-C at the local console.
  2528. ;
  2529. wloop:           mov  ah,1             ;check for console keys
  2530.            int  16h
  2531.            jz   wloop1             ;jmp if no key
  2532.            mov  ah,0
  2533.            int  16h              ;get the key pressed
  2534.            cmp  al,CTRL_C
  2535.            jne  wloop1             ;ctrl-c pressed?
  2536.            mov  si,OFFSET halt_msg         ;ask user what to do
  2537.            call con_puts
  2538. ;
  2539. ; Ctrl-C was pressed ask the user what he wants to do.
  2540. ;
  2541. wloop0:        mov  ah,1             ;check for con key press
  2542.            int  16h
  2543.            jz   wloop0             ;jmp if no key
  2544.            mov  ah,0
  2545.            int  16h              ;get the key pressed
  2546.            cmp  al,61h             ;check for upper case
  2547.            jl   wloop2
  2548.            cmp  al,7Ah
  2549.            jg   wloop2
  2550.            and  al,0DFh             ;make upper case
  2551.  
  2552. wloop2:        cmp  al,'R'             ;'R' to resume call wait
  2553.            jne  loc_ctrl
  2554.            jmp  call_restart
  2555. loc_ctrl:
  2556.          IF LOGON_EXE
  2557.            cmp  al,'E'             ;'E' execute BYE locally
  2558.            jne  loc_ctrl1
  2559.            mov  locl_flg,YES
  2560.            jmp  getnulls
  2561.          ENDIF
  2562.  
  2563. loc_ctrl1:     cmp  al,CR             ;CR to exit BYE to DOS
  2564.            jne  wloop0
  2565. loc_ctrl3:     mov  si,OFFSET exit_msg
  2566.            call con_puts
  2567.            mov  ax,OFF             ;turn off dtr.
  2568.            call port_dtr
  2569.            call port_stop             ;turn off interrupts
  2570.            int  20h              ;exit to dos
  2571. ;
  2572. ; Check the modem to see if its ringing. If it is not a ring ignore
  2573. ;the data and jump to see if local keyboard has anything.
  2574. ;
  2575.          IF SMART_MDM
  2576. wloop1:        call rx_ready
  2577.            jz   wloop             ;no char waiting
  2578.            call rx_getc             ;get char from mdm.
  2579.            cmp  al,'2'             ;mdm sent ringing code?
  2580.            jne  wloop1             ; no, try again!
  2581.            call con_putc             ;show character rx-ed
  2582.         ELSE
  2583. wloop1:        call port_cd             ;cd pin active?
  2584.            jnc  wloop             ;jmp if cd not found
  2585.         ENDIF
  2586. ring:           mov  si,OFFSET crlf         ;send a crlf
  2587.            call con_puts
  2588.            mov  ax,2             ;wait a sec for modem to
  2589.            call delay             ; settle.
  2590.          IF SMART_MDM
  2591.            call rx_flush
  2592.            mov  si,OFFSET mdm_answer     ;answer the phone call
  2593.            call mcon_puts             ;send the 'ATA' to modem
  2594.          ENDIF
  2595. ;
  2596. ;  Get the status of the modem answer request. If no carrier was found
  2597. ; hang up the modem and recycle for the next call.
  2598. ;
  2599.          IF SMART_MDM
  2600.            mov  ax,2             ;wait about 1/2 sec
  2601.            call delay
  2602.  
  2603.            mov  cx,4             ;up to 4 chars at max
  2604.            mov  di,OFFSET res_buf         ;ptr to input buffer
  2605.            call mdm_gets             ;get a string from mdm
  2606.            mov  si,OFFSET res_buf
  2607.            call con_puts             ;display result code
  2608.  
  2609.            mov  ax, WORD PTR res_buf     ;read first 2 bytes
  2610.            mov  baud,0
  2611.            mov  bl, '1'             ;code "1" = 300bps
  2612.            mov  bh,0             ;Bell 103 compatable
  2613.            cmp  bx,ax
  2614.            je   answer1
  2615.  
  2616.          IF BPS_1200 OR BPS_2400 OR TELEBIT
  2617.            mov  baud,1
  2618.            mov  bl, '5'             ;code "5" = 1200bps
  2619.            mov  bh,0             ;Bell 212A or V.22
  2620.            cmp  bx,ax
  2621.            je   answer1
  2622.          ENDIF
  2623.  
  2624.          IF BPS_2400 OR TELEBIT
  2625.            mov  baud,2
  2626.            mov  bl, '1'             ;code "10" = 2400bps
  2627.            mov  bh, '0'             ;V.22 compatable
  2628.            cmp  bx,ax
  2629.            je   answer1
  2630.          ENDIF
  2631.  
  2632.          IF TELEBIT
  2633.            mov  baud,3
  2634.            mov  bl, '5'             ;code "50" = 9600bps
  2635.            mov  bh, '0'             ;PEP Protocol
  2636.            cmp  bx,ax
  2637.            je   answer1
  2638.          ENDIF
  2639.  
  2640. no_answer:     mov  si,OFFSET msg_nocd         ;show no carrier msg
  2641.            call con_puts
  2642.            mov  ax,1             ;now wait and recycle
  2643.            call delay
  2644.            jmp  abort_call
  2645.          ENDIF
  2646. ;
  2647. ;  The modem is now locked on to the remote carrier. We must now make
  2648. ; sure the port is set to the correct baud if not at 1200 buad.
  2649. ;
  2650. answer1:
  2651.            mov  si,OFFSET crlf         ;send a cr/lf to console
  2652.            call con_puts
  2653.          IF SMART_MDM
  2654.            mov  ax,2             ;let the modem settle
  2655.          ELSE
  2656.            mov  ax,1             ;let the modem settle
  2657.          ENDIF                 ; after carrier lock!
  2658.            call delay
  2659.            call rx_flush             ;emtpy out rx-buffer
  2660. ;
  2661. ; Check for a CR to sync the baud rate on and to determine buad rate.
  2662. ;
  2663.          IF SMART_MDM
  2664.            call set_baud             ;set from mdm result code
  2665.          ELSE
  2666.            call sync_baud             ;set by sync'ing to cr
  2667.            jnc  abort_call             ;was baud rate set ok?
  2668.          ENDIF
  2669. ;
  2670. ; Caller is on-line, baud rate is set; start mdm status interrupts
  2671. ; that check for loss of carrier. Program will re-boot if lost now.
  2672. ;
  2673.            mov  al,ON             ;turn on modem status
  2674.            mov  ah,INT_STAT          ; interrupts to test
  2675.            call port_imode             ; for loss of carrier.
  2676. ;
  2677. ; Ask the user how many nulls. May need nulls at 2400bps.
  2678. ;
  2679. getnulls:
  2680.          IF USE_NULLS
  2681.            call ask_nulls             ;ask caller for nulls
  2682.            jc   call_online          ;go on if ok
  2683.          ELSE
  2684.            jmp  call_online
  2685.          ENDIF
  2686. ;
  2687. ; Caller flunked the nulls test or rx-trash on baud sync. Start all over
  2688. ;
  2689. abort_call:    mov  ah,INT_STAT          ;mdm status interrupts off
  2690.            mov  al,OFF             ;status int's testing
  2691.            call port_imode             ; for carrier loss.
  2692.            mov  ax,OFF             ;hang up the modem.
  2693.            call port_dtr
  2694.            mov  ax,2             ;let mdm settle after
  2695.            call delay             ; hanging up.
  2696.          IF BPS_300
  2697.            mov  ax,BPS300             ;start at 300 bps
  2698.          ENDIF
  2699.          IF BPS_1200
  2700.            mov  ax,BPS1200             ;start at 1200 bps
  2701.          ENDIF
  2702.          IF BPS_2400
  2703.            mov  ax,BPS2400             ;start at 2400 bps
  2704.          ENDIF
  2705.          IF TELEBIT
  2706.            mov  ax,BPS9600             ;start at 9600 bps
  2707.          ENDIF
  2708.            call port_baud             ;initialize com port
  2709.            call rx_flush             ;clear out any trash
  2710.            mov  ax,ON             ;DTR/RTS back on
  2711.            call port_dtr
  2712.            jmp  call_restart         ;start all over,
  2713.  
  2714. call_online:   mov  si,OFFSET crlf         ;send crlf
  2715.            call con_puts
  2716.            ret                 ;call online rtn completed...
  2717.  
  2718. call_wait      ENDP
  2719. ;
  2720. ;
  2721. ;-----------------------------------------------------------------------
  2722. ; ASK NULLS --- Ask the caller for how many nulls to needed.
  2723. ;
  2724. ;     Exit:    Carry Set - Error getting Nulls Response from caller
  2725. ;        Carry Clr - Caller Answered Nulls Question ok
  2726. ;
  2727. ;-----------------------------------------------------------------------
  2728. ;
  2729.          IF USE_NULLS
  2730. ask_nulls      PROC near
  2731.  
  2732.            mov  si,OFFSET crlf
  2733.            call mcon_puts
  2734.            mov  bx,9             ;only 8 tries allowed
  2735. getnulls1:     dec  bx
  2736.            cmp  bx,0
  2737.            je   flunked             ;screwed up the iq test?
  2738.            mov  si,OFFSET mdm_nulls
  2739.            call mcon_puts             ;ask nulls question.
  2740. getnulls2:     call rx_ready
  2741.            jnz  getnulls3
  2742.            mov  ah,1             ;check for console keys
  2743.            int  16h
  2744.            jz   getnulls2             ;jmp if no key
  2745.            mov  ah,0
  2746.            int  16h              ;get the key pressed
  2747.            jmp  SHORT getnulls4
  2748. getnulls3:     call rx_getc             ;get a response.
  2749. getnulls4:     call mcon_putc             ;show character rx-ed.
  2750.            cmp  al,'0'
  2751.            jl   getnulls1
  2752.            cmp  al,'9'
  2753.            jg   getnulls1
  2754.            sub  al,30h             ;convert to 0-9 base
  2755.            mov  nulls,al             ;store # of nulls to send
  2756.            jmp  SHORT ask_ok
  2757. flunked:       mov  si,OFFSET mdm_flunk
  2758.            call mcon_puts             ;fall through to abort
  2759. ask_err:       clc                 ;clear the carry flag
  2760.            jmp  SHORT ask_ok1
  2761. ask_ok:        mov  si,OFFSET crlf
  2762.            call mcon_puts
  2763.            stc                 ;set carry flag
  2764. ask_ok1:       ret
  2765.  
  2766. ask_nulls      ENDP
  2767. ;
  2768.          ENDIF
  2769. ;
  2770. ;-----------------------------------------------------------------------
  2771. ; SET BAUD RATE -- Sets the baud rate of caller according to the baud
  2772. ; rate flag that was set by the modem result code sent on answer.
  2773. ;
  2774. ;    baud = 0  300bps
  2775. ;         = 1  1200bps
  2776. ;         = 2  2400bps
  2777. ;         = 3  9600bps (Telebit Modem already set to 9600)
  2778. ;
  2779. ;-----------------------------------------------------------------------
  2780. ;
  2781.          IF SMART_MDM
  2782. ;
  2783. set_baud       PROC near
  2784.  
  2785.            mov  al,baud
  2786.            or   al,al
  2787.            jz   set_300        ;0 = 300bps
  2788.          IF BPS_1200 OR BPS_2400 OR TELEBIT
  2789.            dec  al
  2790.            jz   set_1200        ;1 = 1200bps
  2791.          ENDIF
  2792.          IF BPS_2400 OR TELEBIT
  2793.            dec  al
  2794.            jz   set_2400        ;2 = 2400bps
  2795.          ENDIF
  2796.          IF TELEBIT
  2797.            dec  al
  2798.            jz   set_9600        ;3 = 9600bps
  2799.          ENDIF
  2800.            jmp  SHORT set_1200         ;error!, reset to 1200bps
  2801.  
  2802. set_300:       mov  ax,BPS300             ;reset port to 300 bps
  2803.            mov  si,OFFSET msg_300
  2804.            jmp  SHORT set_end
  2805.  
  2806.          IF BPS_1200 OR BPS_2400 OR TELEBIT
  2807. set_1200:      mov  ax,BPS1200             ;reset port to 1200 bps
  2808.            mov  si,OFFSET msg_1200
  2809.            jmp  SHORT set_end
  2810.          ENDIF
  2811.  
  2812.          IF BPS_2400 OR TELEBIT
  2813. set_2400:      mov  ax,BPS2400             ;reset port to 2400 bps
  2814.            mov  si,OFFSET msg_2400
  2815.            jmp  SHORT set_end
  2816.          ENDIF
  2817.  
  2818.          IF TELEBIT
  2819. set_9600:      mov  ax,BPS9600             ;reset port to 9600 bps
  2820.            mov  si,OFFSET msg_tbit
  2821.          ENDIF
  2822. set_end:
  2823.          IFE TELEBIT
  2824.            call port_baud             ;set the baud rate
  2825.          ENDIF
  2826.            call con_puts             ;show baud rate setting
  2827.            mov  si,OFFSET crlf         ; and send a new line
  2828.            call con_puts
  2829.            mov  ax,2             ;wait a second...
  2830.            call delay
  2831.            call rx_flush             ;clear any trash
  2832.            ret
  2833.  
  2834. set_baud       ENDP
  2835. ;
  2836.          ELSE     ; Its not a smart modem....
  2837. ;
  2838. ;-----------------------------------------------------------------------
  2839. ; SYNC BAUD RATE -- Look for a CR to determine what baud rate the call
  2840. ; is at. If unable to lock on to the baud rate then return with the
  2841. ; carry flag set, else clear the carry flag.
  2842. ;
  2843. ;     Exit:    Carry Set - Baud rate determined and set
  2844. ;        Carry Clr - Error during baud rate sync
  2845. ;
  2846. ;-----------------------------------------------------------------------
  2847. ;
  2848. sync_baud      PROC near
  2849.  
  2850.            mov  cx, 15             ;try 15 times
  2851.  
  2852. sync_baud1:    mov  ax,BPS300             ;try 300 bps
  2853.            call port_baud
  2854.            call rx_flush
  2855.            mov  baud,0
  2856.            mov  si,OFFSET msg_300
  2857.            call con_puts
  2858.            call sync_cr
  2859.            jc   sync_ok
  2860.  
  2861.          IF BPS_1200 OR BPS_2400
  2862.            mov  ax,BPS1200             ;try 1200 bps
  2863.            call port_baud
  2864.            call rx_flush
  2865.            mov  baud,1
  2866.            mov  si,OFFSET msg_1200
  2867.            call con_puts
  2868.            call sync_cr
  2869.            jc   sync_ok
  2870.          ENDIF
  2871.  
  2872.          IF BPS_2400
  2873.            mov  ax,BPS2400             ;try 2400bps
  2874.            call port_baud
  2875.            call rx_flush
  2876.            mov  baud,2
  2877.            mov  si,OFFSET msg_2400
  2878.            call con_puts
  2879.            call sync_cr
  2880.            jc   sync_ok
  2881.          ENDIF
  2882.  
  2883.            loop sync_baud1             ;jmp not enough trash yet.
  2884. sync_err:      clc                 ;clear the carry flag
  2885.            jmp  SHORT sync_ok1
  2886. sync_ok:       stc                 ;set the carry flag
  2887. sync_ok1:      ret
  2888.  
  2889. sync_baud      ENDP
  2890. ;
  2891. ;
  2892. ;-----------------------------------------------------------------------
  2893. ; SYNC TO <CR> -- Look for a CR/Ctrl-C to determine what baud rate.
  2894. ;
  2895. ;     Exit:    Carry Set - Found a CR or Ctrl-C ok
  2896. ;        Carry Clr - Error getting CR or Ctrl-C
  2897. ;
  2898. ;-----------------------------------------------------------------------
  2899. ;
  2900. sync_cr        PROC near
  2901.  
  2902.            push cx
  2903.            mov  cx,20             ;try 20 times
  2904. sync_cr0:      call rx_getc             ;get a character
  2905.            cmp  al,CR
  2906.            je   sync_cr1             ;jump if CR found
  2907.            cmp  al,CTRL_C
  2908.            je   sync_cr1             ;jump if ^C, else
  2909.            mov  ax,1             ; delay for a sec
  2910.            call timer             ; and try again...
  2911.            loop sync_cr0
  2912.            clc                 ;clear carry, error
  2913.            jmp  SHORT sync_cr2
  2914. sync_cr1:      stc                 ;set carry, its sync'ed
  2915. sync_cr2:      pop  cx
  2916.            ret
  2917.  
  2918. sync_cr        ENDP
  2919. ;
  2920.          ENDIF
  2921. ;
  2922. ;
  2923. ;-----------------------------------------------------------------------
  2924. ; MODEM GET STRING -- Get a string from the modem and place the results
  2925. ; in the buffer pointed to by DS:SI. This function will input up to 'n'
  2926. ; characters in the CX register or until a CR or LF is received. Any
  2927. ; CR or LF received is replaced by a null terminating character.
  2928. ;
  2929. ;
  2930. ;   Entry:     DS:DI - Buffer to place data in
  2931. ;          CX - Maximum characters to input
  2932. ;
  2933. ;-----------------------------------------------------------------------
  2934. ;
  2935. mdm_gets       PROC near
  2936.  
  2937.            cld                 ;set 'fwd' direction
  2938. gets1:           call rx_getc             ;get the character
  2939.            cmp  ax,EOF             ;skip error.
  2940.            je   gets1             ;error reading char?
  2941.            cmp  al, CR             ;break on CR
  2942.            je   gets_end
  2943.            cmp  al, LF             ;break on LF
  2944.            je   gets_end
  2945.            mov  [di],al             ;store it in buffer
  2946.            inc  di
  2947.            loop gets1
  2948.  
  2949. gets_end:      mov  al,0             ;null terminate string
  2950.            mov  [di],al             ;store it in buffer
  2951.            ret
  2952.  
  2953. mdm_gets       ENDP
  2954. ;
  2955. ;
  2956. ;-----------------------------------------------------------------------
  2957. ; MODEM PUT STRING -- Send the modem a string at DS:DI. The string must
  2958. ; contain a "$" character to signal the end of the string.
  2959. ;
  2960. ;   Entry:     DS:SI - Points to the string of chars to send
  2961. ;
  2962. ;-----------------------------------------------------------------------
  2963. ;
  2964. mdm_puts       PROC near
  2965.  
  2966.            push ax
  2967.            cld
  2968. mdmputs1:      lodsb            ;get a byte from string
  2969.            cmp  al,'$'        ;if '$', end of string
  2970.            je   mdmputs2
  2971.            cmp  al,0        ;if null, end of string
  2972.            je   mdmputs2
  2973.            call tx_putc        ;send char to modem
  2974.            jmp  SHORT mdmputs1    ;continue looping
  2975. mdmputs2:      pop  ax
  2976.            ret
  2977.  
  2978. mdm_puts       ENDP
  2979. ;
  2980. ;
  2981. ;-----------------------------------------------------------------------
  2982. ; MODEM & CONSOLE PUT STRING -- Send the modem a string at DS:DI.
  2983. ; The string must contain a "$" character to signal the end of string.
  2984. ;
  2985. ;   Entry:     DS:SI - Points to the string of chars to send
  2986. ;
  2987. ;-----------------------------------------------------------------------
  2988. ;
  2989. mcon_puts      PROC near
  2990.  
  2991.            push ax
  2992.            cld
  2993. cputs1:        lodsb            ;get a byte from string
  2994.            cmp  al,'$'        ;if '$', end of string
  2995.            je   cputs2
  2996.            cmp  al,0        ;if null, end of string
  2997.            je   cputs2
  2998.            call mcon_putc        ;send char to modem & screen
  2999.            jmp  SHORT cputs1    ;continue looping
  3000. cputs2:        pop  ax
  3001.            ret
  3002.  
  3003. mcon_puts      ENDP
  3004. ;
  3005. ;
  3006. ;-----------------------------------------------------------------------
  3007. ; MODEM & CONSOLE PUT CHAR -- Send a character to the local console
  3008. ; and the modem.
  3009. ;-----------------------------------------------------------------------
  3010. ;
  3011. mcon_putc      PROC near
  3012.  
  3013.            cmp  locl_flg,0        ;local mode?
  3014.            jne  mcon_putc1        ;yes, skip modem
  3015.            call tx_putc        ;send char to modem
  3016. mcon_putc1:    mov  ah,0Eh        ;write tty function
  3017.            int  10h         ;video bios call
  3018.            ret
  3019.  
  3020. mcon_putc      ENDP
  3021. ;
  3022. ;
  3023. ;-----------------------------------------------------------------------
  3024. ;  FREE MEMORY -- This routine releases the memory used after BYE is
  3025. ; loaded so that other programs will have memory to execute.
  3026. ;-----------------------------------------------------------------------
  3027. ;
  3028.          IF LOGON_EXE
  3029. free_mem       PROC near
  3030.  
  3031.            mov  ax,cs             ;ES=CS
  3032.            mov  es,ax
  3033.            mov  bx,OFFSET eom         ;get end of memory
  3034.            mov  cl,4
  3035.            shr  bx,cl             ;BX divided by 16
  3036.            inc  bx                 ;case not multiple of 16
  3037.            mov  ah,4Ah             ;code for memory release
  3038.            int  21h
  3039.            jnc  free_ok             ;memory free ok?
  3040.            mov  al,BELL             ;ring the bell
  3041.            call con_putc
  3042.            mov  si,OFFSET free_err_msg   ; no, print error msg
  3043.            call con_puts             ; and abort execute.
  3044. free_ok:       ret
  3045.  
  3046. free_mem       ENDP
  3047. ;
  3048. ;
  3049. ;-----------------------------------------------------------------------
  3050. ; EXECUTE A CHILD PROCESS -- This function will execute either a .COM
  3051. ; or an .EXE file and return control to the caller.
  3052. ;-----------------------------------------------------------------------
  3053. ;
  3054. exec_pgm       PROC near
  3055.  
  3056.            mov  ax,cs             ;ES=CS
  3057.            mov  es,ax
  3058.  
  3059.            mov  dx,OFFSET child_name     ;file to execute
  3060.            mov  bx,OFFSET child_parms    ;es:bx -> paramater block
  3061.            mov  cx,cs:[2Ch]          ;set SEGMENT addrs of
  3062.            mov  environ_seg,cx         ; environment blk passed.
  3063.            mov  command_off,80h
  3064.            mov  command_seg,cs
  3065.            mov  fcb1_off,5Ch
  3066.            mov  fcb1_seg,cs
  3067.            mov  fcb2_off,6Ch
  3068.            mov  fcb2_seg,cs
  3069.            cli
  3070.            mov  stk_ptr,sp             ;get stack pointer
  3071.            mov  stk_seg,ss
  3072.            sti
  3073. ;
  3074. ; -- now execute the child process and return control
  3075. ;
  3076.            mov  ax,4B00h             ;execute a child process
  3077.            int  21h
  3078.            jnc  exec_ok             ;exec ok?
  3079.            mov  al,BELL             ;ring the bell
  3080.            call con_putc
  3081.            mov  si,OFFSET exec_err_msg   ;no, print error msg
  3082.            call con_puts             ;and abort execute.
  3083.  
  3084. exec_ok:       mov  ax,cs             ;set SEGMENTs back up
  3085.            mov  es,ax
  3086.            mov  ds,ax
  3087.            cli                 ;halt int's temoporarily
  3088.            mov  ss,stk_seg             ;restore stack segment
  3089.            mov  sp,stk_ptr             ;restore stack ptr
  3090.            sti
  3091.            ret
  3092.  
  3093. exec_pgm       ENDP
  3094. ;
  3095. ;
  3096. ;-----------------------------------------------------------------------
  3097. ;         --- Data area for executable programs ---
  3098. ;-----------------------------------------------------------------------
  3099. ;
  3100. child_name     db   "C:\SYSTEM\XBBS\XBBS.EXE"
  3101.            db   0
  3102. child_parms    equ  $                 ;passed to calling module
  3103. environ_seg    dw   ?
  3104. command_off    dw   ?
  3105. command_seg    dw   ?
  3106. fcb1_off       dw   ?
  3107. fcb1_seg       dw   ?
  3108. fcb2_off       dw   ?
  3109. fcb2_seg       dw   ?
  3110. stk_ptr        dw   ?
  3111. stk_seg        dw   ?
  3112.          ENDIF
  3113.  
  3114. eom           equ $                 ;end of pgm memory marker
  3115. ;
  3116. ;-----------------------------------------------------------------------
  3117. ; End of Program Code
  3118. ;-----------------------------------------------------------------------
  3119. ;
  3120. code           ENDS           ;end of segment
  3121.            END start       ;end of program from start
  3122.  
  3123.